Author: Antonio Cuni <anto.c...@gmail.com> Branch: py3k Changeset: r52923:9e1b5a6a8752 Date: 2012-02-27 11:43 +0100 http://bitbucket.org/pypy/pypy/changeset/9e1b5a6a8752/
Log: hg merge default diff --git a/lib-python/modified-2.7/ctypes/test/test_arrays.py b/lib-python/modified-2.7/ctypes/test/test_arrays.py --- a/lib-python/modified-2.7/ctypes/test/test_arrays.py +++ b/lib-python/modified-2.7/ctypes/test/test_arrays.py @@ -1,12 +1,23 @@ import unittest from ctypes import * +from test.test_support import impl_detail formats = "bBhHiIlLqQfd" +# c_longdouble commented out for PyPy, look at the commend in test_longdouble formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ - c_long, c_ulonglong, c_float, c_double, c_longdouble + c_long, c_ulonglong, c_float, c_double #, c_longdouble class ArrayTestCase(unittest.TestCase): + + @impl_detail('long double not supported by PyPy', pypy=False) + def test_longdouble(self): + """ + This test is empty. It's just here to remind that we commented out + c_longdouble in "formats". If pypy will ever supports c_longdouble, we + should kill this test and uncomment c_longdouble inside formats. + """ + def test_simple(self): # create classes holding simple numeric types, and check # various properties. 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 @@ -33,7 +33,7 @@ from pypy.jit.backend.x86.support import values_array from pypy.jit.backend.x86 import support from pypy.rlib.debug import (debug_print, debug_start, debug_stop, - have_debug_prints, fatalerror_notb) + have_debug_prints) from pypy.rlib import rgc from pypy.rlib.clibffi import FFI_DEFAULT_ABI from pypy.jit.backend.x86.jump import remap_frame_layout @@ -104,7 +104,6 @@ self._debug = v def setup_once(self): - self._check_sse2() # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() @@ -162,28 +161,6 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') - _CHECK_SSE2_FUNC_PTR = lltype.Ptr(lltype.FuncType([], lltype.Signed)) - - def _check_sse2(self): - if WORD == 8: - return # all x86-64 CPUs support SSE2 - if not self.cpu.supports_floats: - return # the CPU doesn't support float, so we don't need SSE2 - # - from pypy.jit.backend.x86.detect_sse2 import INSNS - mc = codebuf.MachineCodeBlockWrapper() - for c in INSNS: - mc.writechar(c) - rawstart = mc.materialize(self.cpu.asmmemmgr, []) - fnptr = rffi.cast(self._CHECK_SSE2_FUNC_PTR, rawstart) - features = fnptr() - if bool(features & (1<<25)) and bool(features & (1<<26)): - return # CPU supports SSE2 - fatalerror_notb( - "This version of PyPy was compiled for a x86 CPU supporting SSE2.\n" - "Your CPU is too old. Please translate a PyPy with the option:\n" - "--jit-backend=x86-without-sse2") - def _build_float_constants(self): datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, []) float_constants = datablockwrapper.malloc_aligned(32, alignment=16) diff --git a/pypy/jit/backend/x86/detect_sse2.py b/pypy/jit/backend/x86/detect_sse2.py --- a/pypy/jit/backend/x86/detect_sse2.py +++ b/pypy/jit/backend/x86/detect_sse2.py @@ -1,18 +1,17 @@ import autopath +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.rmmap import alloc, free -INSNS = ("\xB8\x01\x00\x00\x00" # MOV EAX, 1 - "\x53" # PUSH EBX - "\x0F\xA2" # CPUID - "\x5B" # POP EBX - "\x92" # XCHG EAX, EDX - "\xC3") # RET def detect_sse2(): - from pypy.rpython.lltypesystem import lltype, rffi - from pypy.rlib.rmmap import alloc, free data = alloc(4096) pos = 0 - for c in INSNS: + for c in ("\xB8\x01\x00\x00\x00" # MOV EAX, 1 + "\x53" # PUSH EBX + "\x0F\xA2" # CPUID + "\x5B" # POP EBX + "\x92" # XCHG EAX, EDX + "\xC3"): # RET data[pos] = c pos += 1 fnptr = rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Signed)), data) diff --git a/pypy/jit/backend/x86/support.py b/pypy/jit/backend/x86/support.py --- a/pypy/jit/backend/x86/support.py +++ b/pypy/jit/backend/x86/support.py @@ -1,6 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, rffi, llmemory from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.jit.backend.x86.arch import WORD def values_array(TP, size): @@ -37,8 +38,13 @@ if sys.platform == 'win32': ensure_sse2_floats = lambda : None + # XXX check for SSE2 on win32 too else: + if WORD == 4: + extra = ['-DPYPY_X86_CHECK_SSE2'] + else: + extra = [] ensure_sse2_floats = rffi.llexternal_use_eci(ExternalCompilationInfo( compile_extra = ['-msse2', '-mfpmath=sse', - '-DPYPY_CPU_HAS_STANDARD_PRECISION'], + '-DPYPY_CPU_HAS_STANDARD_PRECISION'] + extra, )) diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py --- a/pypy/jit/metainterp/test/test_quasiimmut.py +++ b/pypy/jit/metainterp/test/test_quasiimmut.py @@ -8,7 +8,7 @@ from pypy.jit.metainterp.quasiimmut import get_current_qmut_instance from pypy.jit.metainterp.test.support import LLJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy -from pypy.rlib.jit import JitDriver, dont_look_inside +from pypy.rlib.jit import JitDriver, dont_look_inside, unroll_safe def test_get_current_qmut_instance(): @@ -480,6 +480,32 @@ assert res == 1 self.check_jitcell_token_count(2) + def test_for_loop_array(self): + myjitdriver = JitDriver(greens=[], reds=["n", "i"]) + class Foo(object): + _immutable_fields_ = ["x?[*]"] + def __init__(self, x): + self.x = x + f = Foo([1, 3, 5, 6]) + @unroll_safe + def g(v): + for x in f.x: + if x & 1 == 0: + v += 1 + return v + def main(n): + i = 0 + while i < n: + myjitdriver.jit_merge_point(n=n, i=i) + i = g(i) + return i + res = self.meta_interp(main, [10]) + assert res == 10 + self.check_resops({ + "int_add": 2, "int_lt": 2, "jump": 1, "guard_true": 2, + "guard_not_invalidated": 2 + }) + class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin): pass diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -170,7 +170,7 @@ space = make_objspace(config) space.appexec([space.wrap(str(tmpfile))], """(tmpfile): import io - f = io.open(tmpfile, 'w') + f = io.open(tmpfile, 'w', encoding='ascii') f.write('42') # no flush() and no close() import sys; sys._keepalivesomewhereobscure = f diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -406,7 +406,7 @@ }.items(): GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr) - for cpyname in 'Method List Int Long Dict Tuple'.split(): + for cpyname in 'Method List Long Dict Tuple'.split(): FORWARD_DECLS.append('typedef struct { PyObject_HEAD } ' 'Py%sObject' % (cpyname, )) build_exported_objects() diff --git a/pypy/module/cpyext/include/intobject.h b/pypy/module/cpyext/include/intobject.h --- a/pypy/module/cpyext/include/intobject.h +++ b/pypy/module/cpyext/include/intobject.h @@ -7,6 +7,11 @@ extern "C" { #endif +typedef struct { + PyObject_HEAD + long ob_ival; +} PyIntObject; + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py --- a/pypy/module/cpyext/intobject.py +++ b/pypy/module/cpyext/intobject.py @@ -2,11 +2,37 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.interpreter.error import OperationError from pypy.module.cpyext.api import ( - cpython_api, build_type_checkers, PyObject, - CONST_STRING, CANNOT_FAIL, Py_ssize_t) + cpython_api, cpython_struct, build_type_checkers, bootstrap_function, + PyObject, PyObjectFields, CONST_STRING, CANNOT_FAIL, Py_ssize_t) +from pypy.module.cpyext.pyobject import ( + make_typedescr, track_reference, RefcountState, from_ref) from pypy.rlib.rarithmetic import r_uint, intmask, LONG_TEST +from pypy.objspace.std.intobject import W_IntObject import sys +PyIntObjectStruct = lltype.ForwardReference() +PyIntObject = lltype.Ptr(PyIntObjectStruct) +PyIntObjectFields = PyObjectFields + \ + (("ob_ival", rffi.LONG),) +cpython_struct("PyIntObject", PyIntObjectFields, PyIntObjectStruct) + +@bootstrap_function +def init_intobject(space): + "Type description of PyIntObject" + make_typedescr(space.w_int.instancetypedef, + basestruct=PyIntObject.TO, + realize=int_realize) + +def int_realize(space, obj): + intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) + w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) + w_obj = space.allocate_instance(W_IntObject, w_type) + w_obj.__init__(intval) + track_reference(space, obj, w_obj) + state = space.fromcache(RefcountState) + state.set_lifeline(w_obj, obj) + return w_obj + PyInt_Check, PyInt_CheckExact = build_type_checkers("Int") @cpython_api([], lltype.Signed, error=CANNOT_FAIL) diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -193,7 +193,7 @@ if not obj: PyErr_NoMemory(space) obj.c_ob_type = type - _Py_NewReference(space, obj) + obj.c_ob_refcnt = 1 return obj @cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject) diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -17,6 +17,7 @@ class BaseCpyTypedescr(object): basestruct = PyObject.TO + W_BaseObject = W_ObjectObject def get_dealloc(self, space): from pypy.module.cpyext.typeobject import subtype_dealloc @@ -51,10 +52,14 @@ def attach(self, space, pyobj, w_obj): pass - def realize(self, space, ref): - # For most types, a reference cannot exist without - # a real interpreter object - raise InvalidPointerException(str(ref)) + def realize(self, space, obj): + w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) + w_obj = space.allocate_instance(self.W_BaseObject, w_type) + track_reference(space, obj, w_obj) + if w_type is not space.gettypefor(self.W_BaseObject): + state = space.fromcache(RefcountState) + state.set_lifeline(w_obj, obj) + return w_obj typedescr_cache = {} @@ -369,13 +374,7 @@ obj.c_ob_refcnt = 1 w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) assert isinstance(w_type, W_TypeObject) - if w_type.is_cpytype(): - w_obj = space.allocate_instance(W_ObjectObject, w_type) - track_reference(space, obj, w_obj) - state = space.fromcache(RefcountState) - state.set_lifeline(w_obj, obj) - else: - assert False, "Please add more cases in _Py_NewReference()" + get_typedescr(w_type.instancetypedef).realize(space, obj) def _Py_Dealloc(space, obj): from pypy.module.cpyext.api import generic_cpy_call_dont_decref diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -117,8 +117,12 @@ flags = lltype.malloc(PyCompilerFlags, flavor='raw') flags.c_cf_flags = rffi.cast(rffi.INT, consts.PyCF_SOURCE_IS_UTF8) w_globals = space.newdict() - api.PyRun_StringFlags("a = u'caf\xc3\xa9'", Py_single_input, - w_globals, w_globals, flags) + buf = rffi.str2charp("a = u'caf\xc3\xa9'") + try: + api.PyRun_StringFlags(buf, Py_single_input, + w_globals, w_globals, flags) + finally: + rffi.free_charp(buf) w_a = space.getitem(w_globals, space.wrap("a")) assert space.unwrap(w_a) == u'caf\xe9' lltype.free(flags, flavor='raw') diff --git a/pypy/module/cpyext/test/test_intobject.py b/pypy/module/cpyext/test/test_intobject.py --- a/pypy/module/cpyext/test/test_intobject.py +++ b/pypy/module/cpyext/test/test_intobject.py @@ -65,4 +65,97 @@ values = module.values() types = [type(x) for x in values] assert types == [int, long, int, int] - + + def test_int_subtype(self): + module = self.import_extension( + 'foo', [ + ("newEnum", "METH_VARARGS", + """ + EnumObject *enumObj; + long intval; + PyObject *name; + + if (!PyArg_ParseTuple(args, "Oi", &name, &intval)) + return NULL; + + PyType_Ready(&Enum_Type); + enumObj = PyObject_New(EnumObject, &Enum_Type); + if (!enumObj) { + return NULL; + } + + enumObj->ob_ival = intval; + Py_INCREF(name); + enumObj->ob_name = name; + + return (PyObject *)enumObj; + """), + ], + prologue=""" + typedef struct + { + PyObject_HEAD + long ob_ival; + PyObject* ob_name; + } EnumObject; + + static void + enum_dealloc(EnumObject *op) + { + Py_DECREF(op->ob_name); + Py_TYPE(op)->tp_free((PyObject *)op); + } + + static PyMemberDef enum_members[] = { + {"name", T_OBJECT, offsetof(EnumObject, ob_name), 0, NULL}, + {NULL} /* Sentinel */ + }; + + PyTypeObject Enum_Type = { + PyObject_HEAD_INIT(0) + /*ob_size*/ 0, + /*tp_name*/ "Enum", + /*tp_basicsize*/ sizeof(EnumObject), + /*tp_itemsize*/ 0, + /*tp_dealloc*/ enum_dealloc, + /*tp_print*/ 0, + /*tp_getattr*/ 0, + /*tp_setattr*/ 0, + /*tp_compare*/ 0, + /*tp_repr*/ 0, + /*tp_as_number*/ 0, + /*tp_as_sequence*/ 0, + /*tp_as_mapping*/ 0, + /*tp_hash*/ 0, + /*tp_call*/ 0, + /*tp_str*/ 0, + /*tp_getattro*/ 0, + /*tp_setattro*/ 0, + /*tp_as_buffer*/ 0, + /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + /*tp_doc*/ 0, + /*tp_traverse*/ 0, + /*tp_clear*/ 0, + /*tp_richcompare*/ 0, + /*tp_weaklistoffset*/ 0, + /*tp_iter*/ 0, + /*tp_iternext*/ 0, + /*tp_methods*/ 0, + /*tp_members*/ enum_members, + /*tp_getset*/ 0, + /*tp_base*/ &PyInt_Type, + /*tp_dict*/ 0, + /*tp_descr_get*/ 0, + /*tp_descr_set*/ 0, + /*tp_dictoffset*/ 0, + /*tp_init*/ 0, + /*tp_alloc*/ 0, + /*tp_new*/ 0 + }; + """) + + a = module.newEnum("ULTIMATE_ANSWER", 42) + assert type(a).__name__ == "Enum" + assert isinstance(a, int) + assert a == int(a) == 42 + assert a.name == "ULTIMATE_ANSWER" diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -362,7 +362,7 @@ def test_cannot_write_pyc(self): import sys, os - p = os.path.join(sys.path[-1], 'readonly') + p = os.path.join(sys.path[0], 'readonly') try: os.chmod(p, 0o555) except: diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -779,8 +779,6 @@ """ Intermediate class for performing binary operations. """ - _immutable_fields_ = ['left', 'right'] - def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right): VirtualArray.__init__(self, name, shape, res_dtype) self.ufunc = ufunc @@ -856,8 +854,6 @@ self.right.create_sig(), done_func) class AxisReduce(Call2): - _immutable_fields_ = ['left', 'right'] - def __init__(self, ufunc, name, identity, shape, dtype, left, right, dim): Call2.__init__(self, ufunc, name, shape, dtype, dtype, left, right) diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py --- a/pypy/module/pypyjit/test_pypy_c/test_instance.py +++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py @@ -201,3 +201,28 @@ loop, = log.loops_by_filename(self.filepath) assert loop.match_by_id("compare", "") # optimized away + def test_super(self): + def main(): + class A(object): + def m(self, x): + return x + 1 + class B(A): + def m(self, x): + return super(B, self).m(x) + i = 0 + while i < 300: + i = B().m(i) + return i + + log = self.run(main, []) + loop, = log.loops_by_filename(self.filepath) + assert loop.match(""" + i78 = int_lt(i72, 300) + guard_true(i78, descr=...) + guard_not_invalidated(descr=...) + i79 = force_token() + i80 = force_token() + i81 = int_add(i72, 1) + --TICK-- + jump(..., descr=...) + """) diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -103,6 +103,7 @@ 'terminator', '_version_tag?', 'name?', + 'mro_w?[*]', ] # for config.objspace.std.getattributeshortcut @@ -345,9 +346,9 @@ return w_self._lookup_where(name) + @unroll_safe def lookup_starting_at(w_self, w_starttype, name): space = w_self.space - # XXX Optimize this with method cache look = False for w_class in w_self.mro_w: if w_class is w_starttype: diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py --- a/pypy/rpython/lltypesystem/rlist.py +++ b/pypy/rpython/lltypesystem/rlist.py @@ -392,7 +392,11 @@ ('list', r_list.lowleveltype), ('index', Signed))) self.ll_listiter = ll_listiter - self.ll_listnext = ll_listnext + if (isinstance(r_list, FixedSizeListRepr) + and not r_list.listitem.mutated): + self.ll_listnext = ll_listnext_foldable + else: + self.ll_listnext = ll_listnext self.ll_getnextindex = ll_getnextindex def ll_listiter(ITERPTR, lst): @@ -409,5 +413,14 @@ iter.index = index + 1 # cannot overflow because index < l.length return l.ll_getitem_fast(index) +def ll_listnext_foldable(iter): + from pypy.rpython.rlist import ll_getitem_foldable_nonneg + l = iter.list + index = iter.index + if index >= l.ll_length(): + raise StopIteration + iter.index = index + 1 # cannot overflow because index < l.length + return ll_getitem_foldable_nonneg(l, index) + def ll_getnextindex(iter): return iter.index diff --git a/pypy/rpython/test/test_rlist.py b/pypy/rpython/test/test_rlist.py --- a/pypy/rpython/test/test_rlist.py +++ b/pypy/rpython/test/test_rlist.py @@ -8,6 +8,7 @@ from pypy.rpython.rlist import * from pypy.rpython.lltypesystem.rlist import ListRepr, FixedSizeListRepr, ll_newlist, ll_fixed_newlist from pypy.rpython.lltypesystem import rlist as ll_rlist +from pypy.rpython.llinterp import LLException from pypy.rpython.ootypesystem import rlist as oo_rlist from pypy.rpython.rint import signed_repr from pypy.objspace.flow.model import Constant, Variable @@ -1477,6 +1478,80 @@ assert func1.oopspec == 'list.getitem_foldable(l, index)' assert not hasattr(func2, 'oopspec') + def test_iterate_over_immutable_list(self): + from pypy.rpython import rlist + class MyException(Exception): + pass + lst = list('abcdef') + def dummyfn(): + total = 0 + for c in lst: + total += ord(c) + return total + # + prev = rlist.ll_getitem_foldable_nonneg + try: + def seen_ok(l, index): + if index == 5: + raise KeyError # expected case + return prev(l, index) + rlist.ll_getitem_foldable_nonneg = seen_ok + e = raises(LLException, self.interpret, dummyfn, []) + assert 'KeyError' in str(e.value) + finally: + rlist.ll_getitem_foldable_nonneg = prev + + def test_iterate_over_immutable_list_quasiimmut_attr(self): + from pypy.rpython import rlist + class MyException(Exception): + pass + class Foo: + _immutable_fields_ = ['lst?[*]'] + lst = list('abcdef') + foo = Foo() + def dummyfn(): + total = 0 + for c in foo.lst: + total += ord(c) + return total + # + prev = rlist.ll_getitem_foldable_nonneg + try: + def seen_ok(l, index): + if index == 5: + raise KeyError # expected case + return prev(l, index) + rlist.ll_getitem_foldable_nonneg = seen_ok + e = raises(LLException, self.interpret, dummyfn, []) + assert 'KeyError' in str(e.value) + finally: + rlist.ll_getitem_foldable_nonneg = prev + + def test_iterate_over_mutable_list(self): + from pypy.rpython import rlist + class MyException(Exception): + pass + lst = list('abcdef') + def dummyfn(): + total = 0 + for c in lst: + total += ord(c) + lst[0] = 'x' + return total + # + prev = rlist.ll_getitem_foldable_nonneg + try: + def seen_ok(l, index): + if index == 5: + raise KeyError # expected case + return prev(l, index) + rlist.ll_getitem_foldable_nonneg = seen_ok + res = self.interpret(dummyfn, []) + assert res == sum(map(ord, 'abcdef')) + finally: + rlist.ll_getitem_foldable_nonneg = prev + + class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist type_system = 'ootype' diff --git a/pypy/translator/c/src/asm_gcc_x86.h b/pypy/translator/c/src/asm_gcc_x86.h --- a/pypy/translator/c/src/asm_gcc_x86.h +++ b/pypy/translator/c/src/asm_gcc_x86.h @@ -102,6 +102,12 @@ #endif /* !PYPY_CPU_HAS_STANDARD_PRECISION */ +#ifdef PYPY_X86_CHECK_SSE2 +#define PYPY_X86_CHECK_SSE2_DEFINED +extern void pypy_x86_check_sse2(void); +#endif + + /* implementations */ #ifndef PYPY_NOT_MAIN_FILE @@ -113,4 +119,25 @@ } # endif +# ifdef PYPY_X86_CHECK_SSE2 +void pypy_x86_check_sse2(void) +{ + //Read the CPU features. + int features; + asm("mov $1, %%eax\n" + "cpuid\n" + "mov %%edx, %0" + : "=g"(features) : : "eax", "ebx", "edx", "ecx"); + + //Check bits 25 and 26, this indicates SSE2 support + if (((features & (1 << 25)) == 0) || ((features & (1 << 26)) == 0)) + { + fprintf(stderr, "Old CPU with no SSE2 support, cannot continue.\n" + "You need to re-translate with " + "'--jit-backend=x86-without-sse2'\n"); + abort(); + } +} +# endif + #endif diff --git a/pypy/translator/c/src/debug_print.c b/pypy/translator/c/src/debug_print.c --- a/pypy/translator/c/src/debug_print.c +++ b/pypy/translator/c/src/debug_print.c @@ -1,3 +1,4 @@ +#define PYPY_NOT_MAIN_FILE #include <string.h> #include <stddef.h> diff --git a/pypy/translator/c/src/dtoa.c b/pypy/translator/c/src/dtoa.c --- a/pypy/translator/c/src/dtoa.c +++ b/pypy/translator/c/src/dtoa.c @@ -46,13 +46,13 @@ * of return type *Bigint all return NULL to indicate a malloc failure. * Similarly, rv_alloc and nrv_alloc (return type char *) return NULL on * failure. bigcomp now has return type int (it used to be void) and - * returns -1 on failure and 0 otherwise. _Py_dg_dtoa returns NULL - * on failure. _Py_dg_strtod indicates failure due to malloc failure + * returns -1 on failure and 0 otherwise. __Py_dg_dtoa returns NULL + * on failure. __Py_dg_strtod indicates failure due to malloc failure * by returning -1.0, setting errno=ENOMEM and *se to s00. * * 4. The static variable dtoa_result has been removed. Callers of - * _Py_dg_dtoa are expected to call _Py_dg_freedtoa to free - * the memory allocated by _Py_dg_dtoa. + * __Py_dg_dtoa are expected to call __Py_dg_freedtoa to free + * the memory allocated by __Py_dg_dtoa. * * 5. The code has been reformatted to better fit with Python's * C style guide (PEP 7). @@ -61,7 +61,7 @@ * that hasn't been MALLOC'ed, private_mem should only be used when k <= * Kmax. * - * 7. _Py_dg_strtod has been modified so that it doesn't accept strings with + * 7. __Py_dg_strtod has been modified so that it doesn't accept strings with * leading whitespace. * ***************************************************************/ @@ -283,7 +283,7 @@ #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff -/* struct BCinfo is used to pass information from _Py_dg_strtod to bigcomp */ +/* struct BCinfo is used to pass information from __Py_dg_strtod to bigcomp */ typedef struct BCinfo BCinfo; struct @@ -494,7 +494,7 @@ /* convert a string s containing nd decimal digits (possibly containing a decimal separator at position nd0, which is ignored) to a Bigint. This - function carries on where the parsing code in _Py_dg_strtod leaves off: on + function carries on where the parsing code in __Py_dg_strtod leaves off: on entry, y9 contains the result of converting the first 9 digits. Returns NULL on failure. */ @@ -1050,7 +1050,7 @@ } /* Convert a scaled double to a Bigint plus an exponent. Similar to d2b, - except that it accepts the scale parameter used in _Py_dg_strtod (which + except that it accepts the scale parameter used in __Py_dg_strtod (which should be either 0 or 2*P), and the normalization for the return value is different (see below). On input, d should be finite and nonnegative, and d / 2**scale should be exactly representable as an IEEE 754 double. @@ -1351,9 +1351,9 @@ /* The bigcomp function handles some hard cases for strtod, for inputs with more than STRTOD_DIGLIM digits. It's called once an initial estimate for the double corresponding to the input string has - already been obtained by the code in _Py_dg_strtod. + already been obtained by the code in __Py_dg_strtod. - The bigcomp function is only called after _Py_dg_strtod has found a + The bigcomp function is only called after __Py_dg_strtod has found a double value rv such that either rv or rv + 1ulp represents the correctly rounded value corresponding to the original string. It determines which of these two values is the correct one by @@ -1368,12 +1368,12 @@ s0 points to the first significant digit of the input string. rv is a (possibly scaled) estimate for the closest double value to the - value represented by the original input to _Py_dg_strtod. If + value represented by the original input to __Py_dg_strtod. If bc->scale is nonzero, then rv/2^(bc->scale) is the approximation to the input value. bc is a struct containing information gathered during the parsing and - estimation steps of _Py_dg_strtod. Description of fields follows: + estimation steps of __Py_dg_strtod. Description of fields follows: bc->e0 gives the exponent of the input value, such that dv = (integer given by the bd->nd digits of s0) * 10**e0 @@ -1505,7 +1505,7 @@ } static double -_Py_dg_strtod(const char *s00, char **se) +__Py_dg_strtod(const char *s00, char **se) { int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error; int esign, i, j, k, lz, nd, nd0, odd, sign; @@ -1849,7 +1849,7 @@ for(;;) { - /* This is the main correction loop for _Py_dg_strtod. + /* This is the main correction loop for __Py_dg_strtod. We've got a decimal value tdv, and a floating-point approximation srv=rv/2^bc.scale to tdv. The aim is to determine whether srv is @@ -2283,7 +2283,7 @@ */ static void -_Py_dg_freedtoa(char *s) +__Py_dg_freedtoa(char *s) { Bigint *b = (Bigint *)((int *)s - 1); b->maxwds = 1 << (b->k = *(int*)b); @@ -2325,11 +2325,11 @@ */ /* Additional notes (METD): (1) returns NULL on failure. (2) to avoid memory - leakage, a successful call to _Py_dg_dtoa should always be matched by a - call to _Py_dg_freedtoa. */ + leakage, a successful call to __Py_dg_dtoa should always be matched by a + call to __Py_dg_freedtoa. */ static char * -_Py_dg_dtoa(double dd, int mode, int ndigits, +__Py_dg_dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve) { /* Arguments ndigits, decpt, sign are similar to those @@ -2926,7 +2926,7 @@ if (b) Bfree(b); if (s0) - _Py_dg_freedtoa(s0); + __Py_dg_freedtoa(s0); return NULL; } @@ -2947,7 +2947,7 @@ _PyPy_SET_53BIT_PRECISION_HEADER; _PyPy_SET_53BIT_PRECISION_START; - result = _Py_dg_strtod(s00, se); + result = __Py_dg_strtod(s00, se); _PyPy_SET_53BIT_PRECISION_END; return result; } @@ -2959,14 +2959,14 @@ _PyPy_SET_53BIT_PRECISION_HEADER; _PyPy_SET_53BIT_PRECISION_START; - result = _Py_dg_dtoa(dd, mode, ndigits, decpt, sign, rve); + result = __Py_dg_dtoa(dd, mode, ndigits, decpt, sign, rve); _PyPy_SET_53BIT_PRECISION_END; return result; } void _PyPy_dg_freedtoa(char *s) { - _Py_dg_freedtoa(s); + __Py_dg_freedtoa(s); } /* End PYPY hacks */ diff --git a/pypy/translator/c/src/main.h b/pypy/translator/c/src/main.h --- a/pypy/translator/c/src/main.h +++ b/pypy/translator/c/src/main.h @@ -36,6 +36,9 @@ RPyListOfString *list; pypy_asm_stack_bottom(); +#ifdef PYPY_X86_CHECK_SSE2_DEFINED + pypy_x86_check_sse2(); +#endif instrument_setup(); if (sizeof(void*) != SIZEOF_LONG) { _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit