Author: Christian Tismer <tis...@stackless.com> Branch: win64-stage1 Changeset: r53824:97ab57d7e7d3 Date: 2012-03-20 01:37 +0100 http://bitbucket.org/pypy/pypy/changeset/97ab57d7e7d3/
Log: Merge with default diff --git a/pypy/annotation/classdef.py b/pypy/annotation/classdef.py --- a/pypy/annotation/classdef.py +++ b/pypy/annotation/classdef.py @@ -148,7 +148,6 @@ "the attribute here; the list of read locations is:\n" + '\n'.join([str(loc[0]) for loc in self.read_locations])) - class ClassDef(object): "Wraps a user class." diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py --- a/pypy/jit/backend/test/runner_test.py +++ b/pypy/jit/backend/test/runner_test.py @@ -16,9 +16,11 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException from pypy.jit.codewriter import heaptracker, longlong +from pypy.rlib import longlong2float from pypy.rlib.rarithmetic import intmask, is_valid_int from pypy.jit.backend.detect_cpu import autodetect_main_model_and_size + def boxfloat(x): return BoxFloat(longlong.getfloatstorage(x)) @@ -1615,6 +1617,12 @@ [BoxPtr(x)], 'int').value assert res == -19 + def test_convert_float_bytes(self): + t = 'int' if longlong.is_64_bit else 'float' + res = self.execute_operation(rop.CONVERT_FLOAT_BYTES_TO_LONGLONG, + [boxfloat(2.5)], t).value + assert res == longlong2float.float2longlong(2.5) + def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py --- a/pypy/jit/backend/test/test_random.py +++ b/pypy/jit/backend/test/test_random.py @@ -449,6 +449,7 @@ OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT)) OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT)) +OPERATIONS.append(CastFloatToIntOperation(rop.CONVERT_FLOAT_BYTES_TO_LONGLONG)) OperationBuilder.OPERATIONS = OPERATIONS @@ -502,11 +503,11 @@ else: assert 0, "unknown backend %r" % pytest.config.option.backend -# ____________________________________________________________ +# ____________________________________________________________ class RandomLoop(object): dont_generate_more = False - + def __init__(self, cpu, builder_factory, r, startvars=None): self.cpu = cpu if startvars is None: 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 @@ -606,7 +606,7 @@ else: assert token struct.number = compute_unique_id(token) - self.loop_run_counters.append(struct) + self.loop_run_counters.append(struct) return struct def _find_failure_recovery_bytecode(self, faildescr): @@ -665,7 +665,7 @@ ResOperation(rop.SETFIELD_RAW, [c_adr, box2], None, descr=self.debug_counter_descr)] operations.extend(ops) - + @specialize.argtype(1) def _inject_debugging_code(self, looptoken, operations, tp, number): if self._debug: @@ -1242,6 +1242,15 @@ self.mc.MOVD_xr(resloc.value, loc0.value) self.mc.CVTSS2SD_xx(resloc.value, resloc.value) + def genop_convert_float_bytes_to_longlong(self, op, arglocs, resloc): + loc0, = arglocs + if longlong.is_64_bit: + assert isinstance(resloc, RegLoc) + assert isinstance(loc0, RegLoc) + self.mc.MOVD(resloc, loc0) + else: + self.mov(loc0, resloc) + def genop_guard_int_is_true(self, op, guard_op, guard_token, arglocs, resloc): guard_opnum = guard_op.getopnum() self.mc.CMP(arglocs[0], imm0) 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 @@ -766,6 +766,18 @@ consider_cast_singlefloat_to_float = consider_cast_int_to_float + def consider_convert_float_bytes_to_longlong(self, op): + if longlong.is_64_bit: + loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0)) + loc1 = self.rm.force_allocate_reg(op.result) + self.Perform(op, [loc0], loc1) + self.xrm.possibly_free_var(op.getarg(0)) + else: + loc0 = self.xrm.loc(op.getarg(0)) + loc1 = self.xrm.force_allocate_reg(op.result) + self.Perform(op, [loc0], loc1) + self.xrm.possibly_free_var(op.getarg(0)) + def _consider_llong_binop_xx(self, op): # must force both arguments into xmm registers, because we don't # know if they will be suitably aligned. Exception: if the second diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -601,9 +601,10 @@ CVTSS2SD_xb = xmminsn('\xF3', rex_nw, '\x0F\x5A', register(1, 8), stack_bp(2)) - MOVD_rx = xmminsn('\x66', rex_nw, '\x0F\x7E', register(2, 8), register(1), '\xC0') - MOVD_xr = xmminsn('\x66', rex_nw, '\x0F\x6E', register(1, 8), register(2), '\xC0') - MOVD_xb = xmminsn('\x66', rex_nw, '\x0F\x6E', register(1, 8), stack_bp(2)) + # These work on machine sized registers. + MOVD_rx = xmminsn('\x66', rex_w, '\x0F\x7E', register(2, 8), register(1), '\xC0') + MOVD_xr = xmminsn('\x66', rex_w, '\x0F\x6E', register(1, 8), register(2), '\xC0') + MOVD_xb = xmminsn('\x66', rex_w, '\x0F\x6E', register(1, 8), stack_bp(2)) PSRAD_xi = xmminsn('\x66', rex_nw, '\x0F\x72', register(1), '\xE0', immediate(2, 'b')) 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 @@ -291,6 +291,11 @@ op1 = SpaceOperation('-live-', [], None) return [op, op1] + def _noop_rewrite(self, op): + return op + + rewrite_op_convert_float_bytes_to_longlong = _noop_rewrite + # ---------- # Various kinds of calls diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py --- a/pypy/jit/codewriter/test/test_flatten.py +++ b/pypy/jit/codewriter/test/test_flatten.py @@ -968,6 +968,15 @@ int_return %i2 """, transform=True) + def test_convert_float_bytes_to_int(self): + from pypy.rlib.longlong2float import float2longlong + def f(x): + return float2longlong(x) + self.encoding_test(f, [25.0], """ + convert_float_bytes_to_longlong %f0 -> %i0 + int_return %i0 + """) + def check_force_cast(FROM, TO, operations, value): """Check that the test is correctly written...""" diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py --- a/pypy/jit/metainterp/blackhole.py +++ b/pypy/jit/metainterp/blackhole.py @@ -1,15 +1,16 @@ +from pypy.jit.codewriter import heaptracker, longlong +from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.metainterp.compile import ResumeAtPositionDescr +from pypy.jit.metainterp.jitexc import JitException, get_llexception, reraise +from pypy.rlib import longlong2float +from pypy.rlib.debug import debug_start, debug_stop, ll_assert, make_sure_not_resized +from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck +from pypy.rlib.rtimer import read_timestamp from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.rtimer import read_timestamp -from pypy.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck -from pypy.rlib.objectmodel import we_are_translated -from pypy.rlib.debug import debug_start, debug_stop, ll_assert -from pypy.rlib.debug import make_sure_not_resized from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rpython.lltypesystem.lloperation import llop -from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr -from pypy.jit.codewriter import heaptracker, longlong -from pypy.jit.metainterp.jitexc import JitException, get_llexception, reraise -from pypy.jit.metainterp.compile import ResumeAtPositionDescr + def arguments(*argtypes, **kwds): resulttype = kwds.pop('returns', None) @@ -20,6 +21,9 @@ return function return decorate +LONGLONG_TYPECODE = 'i' if longlong.is_64_bit else 'f' + + class LeaveFrame(JitException): pass @@ -663,6 +667,11 @@ a = float(a) return longlong.getfloatstorage(a) + @arguments("f", returns=LONGLONG_TYPECODE) + def bhimpl_convert_float_bytes_to_longlong(a): + a = longlong.getrealfloat(a) + return longlong2float.float2longlong(a) + # ---------- # control flow operations @@ -1309,7 +1318,7 @@ def bhimpl_copyunicodecontent(cpu, src, dst, srcstart, dststart, length): cpu.bh_copyunicodecontent(src, dst, srcstart, dststart, length) - @arguments(returns=(longlong.is_64_bit and "i" or "f")) + @arguments(returns=LONGLONG_TYPECODE) def bhimpl_ll_read_timestamp(): return read_timestamp() diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py --- a/pypy/jit/metainterp/pyjitpl.py +++ b/pypy/jit/metainterp/pyjitpl.py @@ -223,6 +223,7 @@ 'cast_float_to_singlefloat', 'cast_singlefloat_to_float', 'float_neg', 'float_abs', 'cast_ptr_to_int', 'cast_int_to_ptr', + 'convert_float_bytes_to_longlong', ]: exec py.code.Source(''' @arguments("box") 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 @@ -419,6 +419,7 @@ 'CAST_INT_TO_FLOAT/1', # need some messy code in the backend 'CAST_FLOAT_TO_SINGLEFLOAT/1', 'CAST_SINGLEFLOAT_TO_FLOAT/1', + 'CONVERT_FLOAT_BYTES_TO_LONGLONG/1', # 'INT_LT/2b', 'INT_LE/2b', diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py --- a/pypy/jit/metainterp/test/test_ajit.py +++ b/pypy/jit/metainterp/test/test_ajit.py @@ -3,6 +3,7 @@ import py from pypy import conftest +from pypy.jit.codewriter import longlong from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy from pypy.jit.metainterp import pyjitpl, history from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT @@ -14,6 +15,7 @@ loop_invariant, elidable, promote, jit_debug, assert_green, AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff, isconstant, isvirtual, promote_string, set_param, record_known_class) +from pypy.rlib.longlong2float import float2longlong from pypy.rlib.rarithmetic import ovfcheck, is_valid_int from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.ootypesystem import ootype @@ -292,7 +294,7 @@ assert res == f(6, sys.maxint, 32, 48) res = self.meta_interp(f, [sys.maxint, 6, 32, 48]) assert res == f(sys.maxint, 6, 32, 48) - + def test_loop_invariant_intbox(self): myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x']) @@ -953,7 +955,7 @@ self.meta_interp(f, [20], repeat=7) # the loop and the entry path as a single trace self.check_jitcell_token_count(1) - + # we get: # ENTER - compile the new loop and the entry bridge # ENTER - compile the leaving path @@ -1470,7 +1472,7 @@ assert res == f(299) self.check_resops(guard_class=0, guard_nonnull=4, guard_nonnull_class=4, guard_isnull=2) - + def test_merge_guardnonnull_guardvalue(self): from pypy.rlib.objectmodel import instantiate @@ -1499,7 +1501,7 @@ assert res == f(299) self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4, guard_nonnull_class=0, guard_isnull=2) - + def test_merge_guardnonnull_guardvalue_2(self): from pypy.rlib.objectmodel import instantiate @@ -1528,7 +1530,7 @@ assert res == f(299) self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4, guard_nonnull_class=0, guard_isnull=2) - + def test_merge_guardnonnull_guardclass_guardvalue(self): from pypy.rlib.objectmodel import instantiate @@ -2636,7 +2638,7 @@ return sa assert self.meta_interp(f, [20]) == f(20) self.check_resops(int_lt=6, int_le=2, int_ge=4, int_gt=3) - + def test_intbounds_not_generalized2(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'node']) @@ -2677,7 +2679,7 @@ assert self.meta_interp(f, [20, 3]) == f(20, 3) self.check_jitcell_token_count(1) self.check_target_token_count(5) - + def test_max_retrace_guards(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a']) @@ -2815,7 +2817,7 @@ for cell in get_stats().get_all_jitcell_tokens(): # Initialal trace with two labels and 5 retraces assert len(cell.target_tokens) <= 7 - + def test_nested_retrace(self): myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'a', 'i', 'j', 'sa']) @@ -3793,6 +3795,16 @@ res = self.interp_operations(g, [1]) assert res == 3 + def test_float2longlong(self): + def f(n): + return float2longlong(n) + + for x in [2.5, float("nan"), -2.5, float("inf")]: + # There are tests elsewhere to verify the correctness of this. + expected = float2longlong(x) + res = self.interp_operations(f, [x]) + assert longlong.getfloatstorage(res) == expected + class TestLLtype(BaseLLtypeTests, LLJitMixin): def test_tagged(self): diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -64,6 +64,8 @@ return dispatcher class BaseType(object): + _attrs_ = () + def _unimplemented_ufunc(self, *args): raise NotImplementedError @@ -241,15 +243,27 @@ _mixin_ = True def _read(self, storage, width, i, offset): - return byteswap(Primitive._read(self, storage, width, i, offset)) + if we_are_translated(): + res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), + width, storage, i, offset) + else: + res = libffi.array_getitem_T(self.T, width, storage, i, offset) + return byteswap(res) def _write(self, storage, width, i, offset, value): - Primitive._write(self, storage, width, i, offset, byteswap(value)) + value = byteswap(value) + if we_are_translated(): + libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T), + width, storage, i, offset, value) + else: + libffi.array_setitem_T(self.T, width, storage, i, offset, value) def pack_str(self, box): return struct.pack(self.format_code, byteswap(self.unbox(box))) class Bool(BaseType, Primitive): + _attrs_ = () + T = lltype.Bool BoxType = interp_boxes.W_BoolBox format_code = "?" @@ -387,83 +401,115 @@ _mixin_ = True class Int8(BaseType, Integer): + _attrs_ = () + T = rffi.SIGNEDCHAR BoxType = interp_boxes.W_Int8Box format_code = "b" NonNativeInt8 = Int8 class UInt8(BaseType, Integer): + _attrs_ = () + T = rffi.UCHAR BoxType = interp_boxes.W_UInt8Box format_code = "B" NonNativeUInt8 = UInt8 class Int16(BaseType, Integer): + _attrs_ = () + T = rffi.SHORT BoxType = interp_boxes.W_Int16Box format_code = "h" class NonNativeInt16(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.SHORT BoxType = interp_boxes.W_Int16Box format_code = "h" class UInt16(BaseType, Integer): + _attrs_ = () + T = rffi.USHORT BoxType = interp_boxes.W_UInt16Box format_code = "H" class NonNativeUInt16(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.USHORT BoxType = interp_boxes.W_UInt16Box format_code = "H" class Int32(BaseType, Integer): + _attrs_ = () + T = rffi.INT BoxType = interp_boxes.W_Int32Box format_code = "i" class NonNativeInt32(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.INT BoxType = interp_boxes.W_Int32Box format_code = "i" class UInt32(BaseType, Integer): + _attrs_ = () + T = rffi.UINT BoxType = interp_boxes.W_UInt32Box format_code = "I" class NonNativeUInt32(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.UINT BoxType = interp_boxes.W_UInt32Box format_code = "I" class Long(BaseType, Integer): + _attrs_ = () + T = rffi.LONG BoxType = interp_boxes.W_LongBox format_code = "l" class NonNativeLong(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.LONG BoxType = interp_boxes.W_LongBox format_code = "l" class ULong(BaseType, Integer): + _attrs_ = () + T = rffi.ULONG BoxType = interp_boxes.W_ULongBox format_code = "L" class NonNativeULong(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.ULONG BoxType = interp_boxes.W_ULongBox format_code = "L" class Int64(BaseType, Integer): + _attrs_ = () + T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box format_code = "q" class NonNativeInt64(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box format_code = "q" @@ -482,6 +528,8 @@ return self.box(value) class UInt64(BaseType, Integer): + _attrs_ = () + T = rffi.ULONGLONG BoxType = interp_boxes.W_UInt64Box format_code = "Q" @@ -489,6 +537,8 @@ _coerce = func_with_new_name(_uint64_coerce, '_coerce') class NonNativeUInt64(BaseType, NonNativeInteger): + _attrs_ = () + T = rffi.ULONGLONG BoxType = interp_boxes.W_UInt64Box format_code = "Q" @@ -790,34 +840,56 @@ class NonNativeFloat(NonNativePrimitive, Float): _mixin_ = True + def _read(self, storage, width, i, offset): + if we_are_translated(): + res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), + width, storage, i, offset) + else: + res = libffi.array_getitem_T(self.T, width, storage, i, offset) + #return byteswap(res) + return res + + def _write(self, storage, width, i, offset, value): + #value = byteswap(value) XXX + if we_are_translated(): + libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T), + width, storage, i, offset, value) + else: + libffi.array_setitem_T(self.T, width, storage, i, offset, value) + + def pack_str(self, box): + # XXX byteswap + return struct.pack(self.format_code, self.unbox(box)) + + class Float32(BaseType, Float): + _attrs_ = () + T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box format_code = "f" class NonNativeFloat32(BaseType, NonNativeFloat): + _attrs_ = () + T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box format_code = "f" class Float64(BaseType, Float): + _attrs_ = () + T = rffi.DOUBLE BoxType = interp_boxes.W_Float64Box format_code = "d" class NonNativeFloat64(BaseType, NonNativeFloat): + _attrs_ = () + T = rffi.DOUBLE BoxType = interp_boxes.W_Float64Box format_code = "d" -class CompositeType(BaseType): - def __init__(self, offsets_and_fields, size): - self.offsets_and_fields = offsets_and_fields - self.size = size - - def get_element_size(self): - return self.size - class BaseStringType(object): _mixin_ = True @@ -841,8 +913,16 @@ NonNativeUnicodeType = UnicodeType -class RecordType(CompositeType): +class RecordType(BaseType): + T = lltype.Char + + def __init__(self, offsets_and_fields, size): + self.offsets_and_fields = offsets_and_fields + self.size = size + + def get_element_size(self): + return self.size def read(self, arr, width, i, offset, dtype=None): if dtype is None: 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 @@ -22,7 +22,7 @@ index = self.index w_length = space.len(self.w_seq) w_len = space.sub(w_length, space.wrap(index)) - if space.is_true(space.lt(w_len,space.wrap(0))): + if space.is_true(space.lt(w_len, space.wrap(0))): w_len = space.wrap(0) return w_len @@ -30,21 +30,21 @@ """Sequence iterator implementation for general sequences.""" class W_FastListIterObject(W_AbstractSeqIterObject): - """Sequence iterator specialized for lists, accessing - directly their RPython-level list of wrapped objects. + """Sequence iterator specialized for lists, accessing directly their + RPython-level list of wrapped objects. """ class W_FastTupleIterObject(W_AbstractSeqIterObject): - """Sequence iterator specialized for tuples, accessing - directly their RPython-level list of wrapped objects. - """ - def __init__(w_self, w_seq, wrappeditems): + """Sequence iterator specialized for tuples, accessing directly + their RPython-level list of wrapped objects. + """ + def __init__(w_self, w_seq, wrappeditems): W_AbstractSeqIterObject.__init__(w_self, w_seq) w_self.tupleitems = wrappeditems class W_ReverseSeqIterObject(W_Object): from pypy.objspace.std.itertype import reverse_iter_typedef as typedef - + def __init__(w_self, space, w_seq, index=-1): w_self.w_seq = w_seq w_self.w_len = space.len(w_seq) @@ -61,15 +61,15 @@ def next__SeqIter(space, w_seqiter): if w_seqiter.w_seq is None: - raise OperationError(space.w_StopIteration, space.w_None) + raise OperationError(space.w_StopIteration, space.w_None) try: w_item = space.getitem(w_seqiter.w_seq, space.wrap(w_seqiter.index)) except OperationError, e: w_seqiter.w_seq = None if not e.match(space, space.w_IndexError): raise - raise OperationError(space.w_StopIteration, space.w_None) - w_seqiter.index += 1 + raise OperationError(space.w_StopIteration, space.w_None) + w_seqiter.index += 1 return w_item # XXX __length_hint__() @@ -89,7 +89,7 @@ except IndexError: w_seqiter.tupleitems = None w_seqiter.w_seq = None - raise OperationError(space.w_StopIteration, space.w_None) + raise OperationError(space.w_StopIteration, space.w_None) w_seqiter.index = index + 1 return w_item @@ -112,7 +112,7 @@ w_item = w_seq.getitem(index) except IndexError: w_seqiter.w_seq = None - raise OperationError(space.w_StopIteration, space.w_None) + raise OperationError(space.w_StopIteration, space.w_None) w_seqiter.index = index + 1 return w_item @@ -126,15 +126,15 @@ def next__ReverseSeqIter(space, w_seqiter): if w_seqiter.w_seq is None or w_seqiter.index < 0: - raise OperationError(space.w_StopIteration, space.w_None) + raise OperationError(space.w_StopIteration, space.w_None) try: w_item = space.getitem(w_seqiter.w_seq, space.wrap(w_seqiter.index)) - w_seqiter.index -= 1 + w_seqiter.index -= 1 except OperationError, e: w_seqiter.w_seq = None if not e.match(space, space.w_IndexError): raise - raise OperationError(space.w_StopIteration, space.w_None) + raise OperationError(space.w_StopIteration, space.w_None) return w_item # XXX __length_hint__() diff --git a/pypy/rlib/bitmanipulation.py b/pypy/rlib/bitmanipulation.py --- a/pypy/rlib/bitmanipulation.py +++ b/pypy/rlib/bitmanipulation.py @@ -1,5 +1,6 @@ from pypy.rlib import unroll + class BitSplitter(dict): def __getitem__(self, lengths): if isinstance(lengths, int): diff --git a/pypy/rlib/longlong2float.py b/pypy/rlib/longlong2float.py --- a/pypy/rlib/longlong2float.py +++ b/pypy/rlib/longlong2float.py @@ -5,7 +5,12 @@ long long to a float and back to a long long. There are corner cases in which it does not work. """ + +from pypy.annotation import model as annmodel +from pypy.rlib.rarithmetic import r_int64 from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.translator.tool.cbuild import ExternalCompilationInfo # -------- implement longlong2float and float2longlong -------- @@ -16,38 +21,33 @@ # these definitions are used only in tests, when not translated def longlong2float_emulator(llval): - d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw') - ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) - ll_array[0] = llval - floatval = d_array[0] - lltype.free(d_array, flavor='raw') - return floatval + with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array: + ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) + ll_array[0] = llval + floatval = d_array[0] + return floatval -def float2longlong_emulator(floatval): - d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw') - ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) - d_array[0] = floatval - llval = ll_array[0] - lltype.free(d_array, flavor='raw') - return llval +def float2longlong(floatval): + with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array: + ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) + d_array[0] = floatval + llval = ll_array[0] + return llval def uint2singlefloat_emulator(ival): - f_array = lltype.malloc(FLOAT_ARRAY_PTR.TO, 1, flavor='raw') - i_array = rffi.cast(UINT_ARRAY_PTR, f_array) - i_array[0] = ival - singlefloatval = f_array[0] - lltype.free(f_array, flavor='raw') - return singlefloatval + with lltype.scoped_alloc(FLOAT_ARRAY_PTR.TO, 1) as f_array: + i_array = rffi.cast(UINT_ARRAY_PTR, f_array) + i_array[0] = ival + singlefloatval = f_array[0] + return singlefloatval def singlefloat2uint_emulator(singlefloatval): - f_array = lltype.malloc(FLOAT_ARRAY_PTR.TO, 1, flavor='raw') - i_array = rffi.cast(UINT_ARRAY_PTR, f_array) - f_array[0] = singlefloatval - ival = i_array[0] - lltype.free(f_array, flavor='raw') - return ival + with lltype.scoped_alloc(FLOAT_ARRAY_PTR.TO, 1) as f_array: + i_array = rffi.cast(UINT_ARRAY_PTR, f_array) + f_array[0] = singlefloatval + ival = i_array[0] + return ival -from pypy.translator.tool.cbuild import ExternalCompilationInfo eci = ExternalCompilationInfo(includes=['string.h', 'assert.h'], post_include_bits=[""" static double pypy__longlong2float(long long x) { @@ -56,12 +56,6 @@ memcpy(&dd, &x, 8); return dd; } -static long long pypy__float2longlong(double x) { - long long ll; - assert(sizeof(double) == 8 && sizeof(long long) == 8); - memcpy(&ll, &x, 8); - return ll; -} static float pypy__uint2singlefloat(unsigned int x) { float ff; assert(sizeof(float) == 4 && sizeof(unsigned int) == 4); @@ -82,12 +76,6 @@ _nowrapper=True, elidable_function=True, sandboxsafe=True, oo_primitive="pypy__longlong2float") -float2longlong = rffi.llexternal( - "pypy__float2longlong", [rffi.DOUBLE], rffi.LONGLONG, - _callable=float2longlong_emulator, compilation_info=eci, - _nowrapper=True, elidable_function=True, sandboxsafe=True, - oo_primitive="pypy__float2longlong") - uint2singlefloat = rffi.llexternal( "pypy__uint2singlefloat", [rffi.UINT], rffi.FLOAT, _callable=uint2singlefloat_emulator, compilation_info=eci, @@ -99,3 +87,15 @@ _callable=singlefloat2uint_emulator, compilation_info=eci, _nowrapper=True, elidable_function=True, sandboxsafe=True, oo_primitive="pypy__singlefloat2uint") + + +class Float2LongLongEntry(ExtRegistryEntry): + _about_ = float2longlong + + def compute_result_annotation(self, s_float): + assert annmodel.SomeFloat().contains(s_float) + return annmodel.SomeInteger(knowntype=r_int64) + + def specialize_call(self, hop): + [v_float] = hop.inputargs(lltype.Float) + return hop.genop("convert_float_bytes_to_longlong", [v_float], resulttype=hop.r_result) diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py --- a/pypy/rlib/rarithmetic.py +++ b/pypy/rlib/rarithmetic.py @@ -578,22 +578,26 @@ T = lltype.typeOf(arg) # XXX we cannot do arithmetics on small ints - arg = widen(arg) + if isinstance(arg, base_int): + arg = widen(arg) if rffi.sizeof(T) == 1: res = arg elif rffi.sizeof(T) == 2: a, b = arg & 0xFF, arg & 0xFF00 res = (a << 8) | (b >> 8) elif rffi.sizeof(T) == 4: - a, b, c, d = arg & 0xFF, arg & 0xFF00, arg & 0xFF0000, arg & r_uint(0xFF000000) + FF = r_uint(0xFF) + arg = r_uint(arg) + a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16), + arg & (FF << 24)) res = (a << 24) | (b << 8) | (c >> 8) | (d >> 24) elif rffi.sizeof(T) == 8: - a, b, c, d = (arg & 0xFF, arg & 0xFF00, arg & 0xFF0000, - arg & r_uint(0xFF000000)) - e, f, g, h = (arg & (r_ulonglong(0xFF) << 32), - arg & (r_ulonglong(0xFF) << 40), - arg & (r_ulonglong(0xFF) << 48), - arg & (r_ulonglong(0xFF) << 56)) + FF = r_ulonglong(0xFF) + arg = r_ulonglong(arg) + a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16), + arg & (FF << 24)) + e, f, g, h = (arg & (FF << 32), arg & (FF << 40), arg & (FF << 48), + arg & (FF << 56)) res = ((a << 56) | (b << 40) | (c << 24) | (d << 8) | (e >> 8) | (f >> 24) | (g >> 40) | (h >> 56)) else: diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py --- a/pypy/rlib/rfloat.py +++ b/pypy/rlib/rfloat.py @@ -1,11 +1,13 @@ """Float constants""" import math + +from pypy.annotation.model import SomeString +from pypy.rlib import objectmodel +from pypy.rpython.extfunc import register_external from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib import objectmodel -from pypy.rpython.extfunc import register_external -from pypy.annotation.model import SomeString + USE_SHORT_FLOAT_REPR = True # XXX make it a translation option? @@ -74,7 +76,7 @@ while i < len(s) and s[i] in '0123456789': after_point += s[i] i += 1 - + if i == len(s): return sign, before_point, after_point, exponent @@ -91,7 +93,7 @@ if i == len(s): raise ValueError - + while i < len(s) and s[i] in '0123456789': exponent += s[i] i += 1 diff --git a/pypy/rlib/rstruct/nativefmttable.py b/pypy/rlib/rstruct/nativefmttable.py --- a/pypy/rlib/rstruct/nativefmttable.py +++ b/pypy/rlib/rstruct/nativefmttable.py @@ -3,14 +3,17 @@ The table 'native_fmttable' is also used by pypy.module.array.interp_array. """ import struct -from pypy.rlib import jit + +from pypy.rlib import jit, longlong2float +from pypy.rlib.objectmodel import specialize +from pypy.rlib.rarithmetic import r_singlefloat, widen from pypy.rlib.rstruct import standardfmttable as std from pypy.rlib.rstruct.error import StructError +from pypy.rlib.unroll import unrolling_iterable +from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rarithmetic import r_singlefloat from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.objectmodel import specialize + native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1) @@ -23,18 +26,24 @@ # ____________________________________________________________ + double_buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', immortal=True) float_buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw', immortal=True) -@jit.dont_look_inside -def double_to_ccharp(doubleval): - double_buf[0] = doubleval - return rffi.cast(rffi.CCHARP, double_buf) +range_8_unroll = unrolling_iterable(list(reversed(range(8)))) +range_4_unroll = unrolling_iterable(list(reversed(range(4)))) def pack_double(fmtiter): doubleval = fmtiter.accept_float_arg() - p = double_to_ccharp(doubleval) - fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.DOUBLE)) + value = longlong2float.float2longlong(doubleval) + if fmtiter.bigendian: + for i in range_8_unroll: + x = (value >> (8*i)) & 0xff + fmtiter.result.append(chr(x)) + else: + for i in range_8_unroll: + fmtiter.result.append(chr(value & 0xff)) + value >>= 8 @specialize.argtype(0) def unpack_double(fmtiter): @@ -45,16 +54,19 @@ doubleval = double_buf[0] fmtiter.appendobj(doubleval) -@jit.dont_look_inside -def float_to_ccharp(floatval): - float_buf[0] = floatval - return rffi.cast(rffi.CCHARP, float_buf) - def pack_float(fmtiter): doubleval = fmtiter.accept_float_arg() floatval = r_singlefloat(doubleval) - p = float_to_ccharp(floatval) - fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.FLOAT)) + value = longlong2float.singlefloat2uint(floatval) + value = widen(value) + if fmtiter.bigendian: + for i in range_4_unroll: + x = (value >> (8*i)) & 0xff + fmtiter.result.append(chr(x)) + else: + for i in range_4_unroll: + fmtiter.result.append(chr(value & 0xff)) + value >>= 8 @specialize.argtype(0) def unpack_float(fmtiter): diff --git a/pypy/rlib/rstruct/standardfmttable.py b/pypy/rlib/rstruct/standardfmttable.py --- a/pypy/rlib/rstruct/standardfmttable.py +++ b/pypy/rlib/rstruct/standardfmttable.py @@ -6,11 +6,12 @@ # values when packing. import struct + +from pypy.rlib.objectmodel import specialize +from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong +from pypy.rlib.rstruct import ieee from pypy.rlib.rstruct.error import StructError, StructOverflowError -from pypy.rlib.rstruct import ieee from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong -from pypy.rlib.objectmodel import specialize # In the CPython struct module, pack() unconsistently accepts inputs # that are out-of-range or floats instead of ints. Should we emulate diff --git a/pypy/translator/c/src/float.h b/pypy/translator/c/src/float.h --- a/pypy/translator/c/src/float.h +++ b/pypy/translator/c/src/float.h @@ -27,7 +27,7 @@ #define OP_FLOAT_SUB(x,y,r) r = x - y #define OP_FLOAT_MUL(x,y,r) r = x * y #define OP_FLOAT_TRUEDIV(x,y,r) r = x / y -#define OP_FLOAT_POW(x,y,r) r = pow(x, y) +#define OP_FLOAT_POW(x,y,r) r = pow(x, y) /*** conversions ***/ @@ -42,5 +42,6 @@ #ifdef HAVE_LONG_LONG #define OP_CAST_FLOAT_TO_LONGLONG(x,r) r = (long long)(x) #define OP_CAST_FLOAT_TO_ULONGLONG(x,r) r = (unsigned long long)(x) +#define OP_CONVERT_FLOAT_BYTES_TO_LONGLONG(x,r) memcpy(&r, &x, sizeof(double)) #endif _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit