From afa at codespeak.net Tue Jun 1 00:07:25 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 00:07:25 +0200 (CEST) Subject: [pypy-svn] r74986 - in pypy/trunk/pypy/module/cpyext: . include test Message-ID: <20100531220725.9F3A4282B9C@codespeak.net> Author: afa Date: Tue Jun 1 00:07:24 2010 New Revision: 74986 Modified: pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/include/Python.h pypy/trunk/pypy/module/cpyext/sliceobject.py pypy/trunk/pypy/module/cpyext/test/comparisons.c pypy/trunk/pypy/module/cpyext/test/foo.c pypy/trunk/pypy/module/cpyext/test/test_object.py Log: Kill most compilation warnings in cpyext tests Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 1 00:07:24 2010 @@ -224,7 +224,8 @@ elif isinstance(input_arg, W_Root): arg = input_arg else: - arg = from_ref(space, input_arg) + arg = from_ref(space, + rffi.cast(PyObject, input_arg)) else: arg = input_arg newargs += (arg, ) @@ -314,7 +315,7 @@ # Standard exceptions for exc_name in exceptions.Module.interpleveldefs.keys(): GLOBALS['PyExc_' + exc_name] = ( - 'PyTypeObject*', + 'PyObject*', 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, )) # Common types with their own struct @@ -568,8 +569,19 @@ members = [] structindex = {} for name, func in FUNCTIONS.iteritems(): - cdecl = db.gettype(func.functype) - members.append(cdecl.replace('@', name) + ';') + restype = db.gettype(func.restype).replace('@', '').strip() + args = [] + for i, argtype in enumerate(func.argtypes): + if argtype is CONST_STRING: + arg = 'const char *@' + elif argtype is CONST_WSTRING: + arg = 'const wchar_t *@' + else: + arg = db.gettype(argtype) + arg = arg.replace('@', 'arg%d' % (i,)).strip() + args.append(arg) + args = ', '.join(args) or "void" + members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) struct_declaration_code = """\ @@ -583,6 +595,8 @@ global_objects = [] for name, (type, expr) in GLOBALS.iteritems(): + if "#" in name: + continue global_objects.append('%s %s = NULL;' % (type, name.replace("#", ""))) global_code = '\n'.join(global_objects) @@ -606,16 +620,35 @@ pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # populate static data - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): from pypy.module import cpyext w_obj = eval(expr) - name = name.replace("#", "") + if name.endswith('#'): + name = name[:-1] + isptr = False + else: + isptr = True INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') - ptr = ctypes.c_void_p.in_dll(bridge, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), - ctypes.c_void_p).value + if isptr: + ptr = ctypes.c_void_p.in_dll(bridge, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), + ctypes.c_void_p).value + elif typ in ('PyObject*', 'PyTypeObject*'): + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge,name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + from pypy.module.cpyext.pyobject import ( + track_reference, get_typedescr) + w_type = space.type(w_obj) + typedescr = get_typedescr(w_type.instancetypedef) + py_obj.c_ob_refcnt = 1 + py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, + make_ref(space, w_type)) + typedescr.attach(space, py_obj, w_obj) + track_reference(space, py_obj, w_obj) + else: + assert False, "Unknown static object: %s %s" % (typ, name) # implement structure initialization code for name, func in FUNCTIONS.iteritems(): @@ -635,17 +668,13 @@ if name.startswith("PyPy"): renamed_symbols.append(name) continue - if "#" in name: - deref = "*" - if not do_deref and not rename: continue - else: - deref = "" - if not rename: continue + if not rename: + continue name = name.replace("#", "") newname = name.replace('Py', 'PyPy') if not rename: newname = name - pypy_macros.append('#define %s %s%s' % (name, deref, newname)) + pypy_macros.append('#define %s %s' % (name, newname)) renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols @@ -666,7 +695,7 @@ pypy_macros_h = udir.join('pypy_macros.h') pypy_macros_h.write('\n'.join(pypy_macros)) -def generate_decls_and_callbacks(db, export_symbols, api_struct=True, globals_are_pointers=True): +def generate_decls_and_callbacks(db, export_symbols, api_struct=True): # implement function callbacks and generate function decls functions = [] pypy_decls = [] @@ -695,7 +724,10 @@ if api_struct: callargs = ', '.join('arg%d' % (i,) for i in range(len(func.argtypes))) - body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) + if func.restype is lltype.Void: + body = "{ _pypyAPI.%s(%s); }" % (name, callargs) + else: + body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) for name in VA_TP_LIST: name_no_star = process_va_name(name) @@ -706,12 +738,10 @@ export_symbols.append('pypy_va_get_%s' % (name_no_star,)) for name, (typ, expr) in GLOBALS.iteritems(): - name_clean = name.replace("#", "") - if not globals_are_pointers: + if name.endswith('#'): + name = name.replace("#", "") typ = typ.replace("*", "") - pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name_clean)) - if not globals_are_pointers and "#" not in name: - pypy_decls.append("#define %s (PyObject*)&%s" % (name, name,)) + pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) pypy_decls.append("#ifdef __cplusplus") pypy_decls.append("}") @@ -739,6 +769,14 @@ else: kwds["includes"] = ['Python.h'] # this is our Python.h + # Generate definitions for global structures + struct_file = udir.join('pypy_structs.c') + structs = ["#include "] + for name, (type, expr) in GLOBALS.iteritems(): + if name.endswith('#'): + structs.append('%s %s;' % (type[:-1], name[:-1])) + struct_file.write('\n'.join(structs)) + eci = ExternalCompilationInfo( include_dirs=include_dirs, separate_module_files=[source_dir / "varargwrapper.c", @@ -751,6 +789,7 @@ source_dir / "bufferobject.c", source_dir / "object.c", source_dir / "cobject.c", + struct_file, ], separate_module_sources = [code], export_symbols=export_symbols_eci, @@ -769,7 +808,7 @@ generate_macros(export_symbols, rename=False, do_deref=False) - functions = generate_decls_and_callbacks(db, [], api_struct=False, globals_are_pointers=False) + functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include \n" + "\n".join(functions) eci = build_eci(False, export_symbols, code) Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Tue Jun 1 00:07:24 2010 @@ -28,15 +28,19 @@ # define Py_LOCAL_INLINE(type) static __inline type __fastcall #endif -#define Py_ssize_t long +#include + +#ifndef _WIN32 +typedef intptr_t Py_ssize_t; +#else +typedef long Py_ssize_t; +#endif #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) #define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) #define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE) #define Py_USING_UNICODE -#include - /* Convert a possibly signed character to a nonnegative int */ /* XXX This assumes characters are 8 bits wide */ #ifdef __CHAR_UNSIGNED__ Modified: pypy/trunk/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/sliceobject.py (original) +++ pypy/trunk/pypy/module/cpyext/sliceobject.py Tue Jun 1 00:07:24 2010 @@ -58,10 +58,10 @@ the new object could not be allocated.""" return W_SliceObject(w_start, w_stop, w_step) - at cpython_api([PyObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, + at cpython_api([PySliceObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP], rffi.INT_real, error=-1) -def PySlice_GetIndicesEx(space, w_slice, length, start_p, stop_p, - step_p, slicelength_p): +def PySlice_GetIndicesEx(space, w_slice, length, start_p, stop_p, step_p, + slicelength_p): """Usable replacement for PySlice_GetIndices(). Retrieve the start, stop, and step indices from the slice object slice assuming a sequence of length length, and store the length of the slice in slicelength. Out Modified: pypy/trunk/pypy/module/cpyext/test/comparisons.c ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/comparisons.c (original) +++ pypy/trunk/pypy/module/cpyext/test/comparisons.c Tue Jun 1 00:07:24 2010 @@ -18,6 +18,7 @@ else if (opid == Py_NE) { return PyBool_FromLong(val != 3); } + return Py_NotImplemented; } static long cmp_hashfunc(PyObject *self) { Modified: pypy/trunk/pypy/module/cpyext/test/foo.c ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/foo.c (original) +++ pypy/trunk/pypy/module/cpyext/test/foo.c Tue Jun 1 00:07:24 2010 @@ -55,7 +55,7 @@ static PyObject * foo_create(fooobject *self) { - return newfooobject(); + return (PyObject*)newfooobject(); } static PyObject * @@ -130,7 +130,7 @@ return -1; self->foo = v; } - return PyObject_GenericSetAttr(self, name, value); + return PyObject_GenericSetAttr((PyObject *)self, name, value); } static PyMemberDef foo_members[] = { @@ -170,7 +170,7 @@ foo_call, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ - foo_setattro, /*tp_setattro*/ + (setattrofunc)foo_setattro, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ @@ -262,7 +262,7 @@ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ - Fuu_init, /*tp_init*/ + (initproc) Fuu_init, /*tp_init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_new*/ 0, /*tp_free Low-level free-memory routine */ Modified: pypy/trunk/pypy/module/cpyext/test/test_object.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_object.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_object.py Tue Jun 1 00:07:24 2010 @@ -202,7 +202,7 @@ ("typecheck", "METH_VARARGS", """ PyObject *obj = PyTuple_GET_ITEM(args, 0); - PyObject *type = PyTuple_GET_ITEM(args, 1); + PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 1); return PyBool_FromLong(PyObject_TypeCheck(obj, type)); """)]) assert module.typecheck(1, int) From afa at codespeak.net Tue Jun 1 00:17:07 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 00:17:07 +0200 (CEST) Subject: [pypy-svn] r74987 - pypy/trunk/pypy/module/cpyext Message-ID: <20100531221707.5863F282B9C@codespeak.net> Author: afa Date: Tue Jun 1 00:17:05 2010 New Revision: 74987 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: small clean-up Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 1 00:17:05 2010 @@ -594,10 +594,10 @@ functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - global_objects.append('%s %s = NULL;' % (type, name.replace("#", ""))) + global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -772,9 +772,9 @@ # Generate definitions for global structures struct_file = udir.join('pypy_structs.c') structs = ["#include "] - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): - structs.append('%s %s;' % (type[:-1], name[:-1])) + structs.append('%s %s;' % (typ[:-1], name[:-1])) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -817,12 +817,12 @@ setup_va_functions(eci) # populate static data - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") from pypy.module import cpyext w_obj = eval(expr) struct_ptr = make_ref(space, w_obj) - struct = rffi.cast(get_structtype_for_ctype(type), struct_ptr)._obj + struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) From afa at codespeak.net Tue Jun 1 00:32:06 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 00:32:06 +0200 (CEST) Subject: [pypy-svn] r74988 - pypy/trunk/pypy/module/cpyext Message-ID: <20100531223206.C5B65282B9C@codespeak.net> Author: afa Date: Tue Jun 1 00:32:05 2010 New Revision: 74988 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Factor out common code Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 1 00:32:05 2010 @@ -552,6 +552,21 @@ for func in BOOTSTRAP_FUNCTIONS: func(space) +def c_function_signature(func): + restype = db.gettype(func.restype).replace('@', '').strip() + args = [] + for i, argtype in enumerate(func.argtypes): + if argtype is CONST_STRING: + arg = 'const char *@' + elif argtype is CONST_WSTRING: + arg = 'const wchar_t *@' + else: + arg = db.gettype(argtype) + arg = arg.replace('@', 'arg%d' % (i,)).strip() + args.append(arg) + args = ', '.join(args) or "void" + return restype, args + #_____________________________________________________ # Build the bridge DLL, Allow extension DLLs to call # back into Pypy space functions @@ -568,19 +583,8 @@ # Structure declaration code members = [] structindex = {} - for name, func in FUNCTIONS.iteritems(): - restype = db.gettype(func.restype).replace('@', '').strip() - args = [] - for i, argtype in enumerate(func.argtypes): - if argtype is CONST_STRING: - arg = 'const char *@' - elif argtype is CONST_WSTRING: - arg = 'const wchar_t *@' - else: - arg = db.gettype(argtype) - arg = arg.replace('@', 'arg%d' % (i,)).strip() - args.append(arg) - args = ', '.join(args) or "void" + for name, func in sorted(FUNCTIONS.iteritems()): + restype, args = c_function_signature(db, fn) members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) @@ -708,18 +712,7 @@ pypy_decls.append("%s;" % (decl,)) for name, func in sorted(FUNCTIONS.iteritems()): - restype = db.gettype(func.restype).replace('@', '').strip() - args = [] - for i, argtype in enumerate(func.argtypes): - if argtype is CONST_STRING: - arg = 'const char *@' - elif argtype is CONST_WSTRING: - arg = 'const wchar_t *@' - else: - arg = db.gettype(argtype) - arg = arg.replace('@', 'arg%d' % (i,)).strip() - args.append(arg) - args = ', '.join(args) or "void" + restype, args = c_function_signature(db, fn) pypy_decls.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args)) if api_struct: callargs = ', '.join('arg%d' % (i,) From afa at codespeak.net Tue Jun 1 00:48:25 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 00:48:25 +0200 (CEST) Subject: [pypy-svn] r74989 - pypy/trunk/pypy/module/cpyext Message-ID: <20100531224825.E0826282B9C@codespeak.net> Author: afa Date: Tue Jun 1 00:48:24 2010 New Revision: 74989 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Oops, must have run tests in another window Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 1 00:48:24 2010 @@ -552,7 +552,7 @@ for func in BOOTSTRAP_FUNCTIONS: func(space) -def c_function_signature(func): +def c_function_signature(db, func): restype = db.gettype(func.restype).replace('@', '').strip() args = [] for i, argtype in enumerate(func.argtypes): @@ -584,7 +584,7 @@ members = [] structindex = {} for name, func in sorted(FUNCTIONS.iteritems()): - restype, args = c_function_signature(db, fn) + restype, args = c_function_signature(db, func) members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) @@ -712,7 +712,7 @@ pypy_decls.append("%s;" % (decl,)) for name, func in sorted(FUNCTIONS.iteritems()): - restype, args = c_function_signature(db, fn) + restype, args = c_function_signature(db, func) pypy_decls.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args)) if api_struct: callargs = ', '.join('arg%d' % (i,) From benjamin at codespeak.net Tue Jun 1 02:41:27 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 1 Jun 2010 02:41:27 +0200 (CEST) Subject: [pypy-svn] r74990 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601004127.3CC36282B9C@codespeak.net> Author: benjamin Date: Tue Jun 1 02:41:25 2010 New Revision: 74990 Modified: pypy/trunk/pypy/module/cpyext/state.py Log: remove identity_dict import Modified: pypy/trunk/pypy/module/cpyext/state.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/state.py (original) +++ pypy/trunk/pypy/module/cpyext/state.py Tue Jun 1 02:41:25 2010 @@ -1,6 +1,5 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import rffi, lltype -from pypy.lib.identity_dict import identity_dict from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import lltype From fijal at codespeak.net Tue Jun 1 05:51:50 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jun 2010 05:51:50 +0200 (CEST) Subject: [pypy-svn] r74991 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601035150.7C45A282B9C@codespeak.net> Author: fijal Date: Tue Jun 1 05:51:47 2010 New Revision: 74991 Modified: pypy/trunk/pypy/module/cpyext/methodobject.py Log: clarify api a bit Modified: pypy/trunk/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/methodobject.py (original) +++ pypy/trunk/pypy/module/cpyext/methodobject.py Tue Jun 1 05:51:47 2010 @@ -234,10 +234,11 @@ def PyDescr_NewMethod(space, w_type, method): return space.wrap(W_PyCMethodObject(space, method, w_type)) -def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, doc, flags, func): +def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, wrapper_func_kwds, + flags, func): # not exactly the API sig return space.wrap(W_PyCWrapperObject(space, pto, method_name, - wrapper_func, doc, flags, func)) + wrapper_func, wrapper_func_kwds, flags, func)) @cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject) def Py_FindMethod(space, table, w_obj, name_ptr): From fijal at codespeak.net Tue Jun 1 05:54:53 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jun 2010 05:54:53 +0200 (CEST) Subject: [pypy-svn] r74992 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601035453.6DFE6282B9C@codespeak.net> Author: fijal Date: Tue Jun 1 05:54:52 2010 New Revision: 74992 Modified: pypy/trunk/pypy/module/cpyext/methodobject.py Log: This is the used signature Modified: pypy/trunk/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/methodobject.py (original) +++ pypy/trunk/pypy/module/cpyext/methodobject.py Tue Jun 1 05:54:52 2010 @@ -235,10 +235,10 @@ return space.wrap(W_PyCMethodObject(space, method, w_type)) def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, wrapper_func_kwds, - flags, func): + doc, func): # not exactly the API sig return space.wrap(W_PyCWrapperObject(space, pto, method_name, - wrapper_func, wrapper_func_kwds, flags, func)) + wrapper_func, wrapper_func_kwds, doc, func)) @cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject) def Py_FindMethod(space, table, w_obj, name_ptr): From fijal at codespeak.net Tue Jun 1 05:57:28 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jun 2010 05:57:28 +0200 (CEST) Subject: [pypy-svn] r74993 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601035728.35FE9282B9C@codespeak.net> Author: fijal Date: Tue Jun 1 05:57:26 2010 New Revision: 74993 Modified: pypy/trunk/pypy/module/cpyext/methodobject.py Log: An assert that should be true in my opinion Modified: pypy/trunk/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/methodobject.py (original) +++ pypy/trunk/pypy/module/cpyext/methodobject.py Tue Jun 1 05:57:26 2010 @@ -125,6 +125,7 @@ self.space = space self.method_name = method_name self.wrapper_func = wrapper_func + assert type(wrapper_func_kwds) is not str self.wrapper_func_kwds = wrapper_func_kwds self.doc = doc self.func = func From afa at codespeak.net Tue Jun 1 09:13:20 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 09:13:20 +0200 (CEST) Subject: [pypy-svn] r74994 - pypy/trunk/pypy/rlib Message-ID: <20100601071320.D998D282B9C@codespeak.net> Author: afa Date: Tue Jun 1 09:13:19 2010 New Revision: 74994 Modified: pypy/trunk/pypy/rlib/rdynload.py Log: Fix a NameError on Windows Modified: pypy/trunk/pypy/rlib/rdynload.py ============================================================================== --- pypy/trunk/pypy/rlib/rdynload.py (original) +++ pypy/trunk/pypy/rlib/rdynload.py Tue Jun 1 09:13:19 2010 @@ -138,7 +138,7 @@ intresource = rffi.cast(rffi.CCHARP, r_uint(index) & 0xFFFF) res = rwin32.GetProcAddress(handle, intresource) if not res: - raise KeyError(name) + raise KeyError(index) # XXX rffi.cast here... return res From afa at codespeak.net Tue Jun 1 11:36:51 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 11:36:51 +0200 (CEST) Subject: [pypy-svn] r74995 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601093651.F1F4B282B9C@codespeak.net> Author: afa Date: Tue Jun 1 11:36:50 2010 New Revision: 74995 Modified: pypy/trunk/pypy/module/cpyext/methodobject.py Log: This may fix a translation issue Modified: pypy/trunk/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/methodobject.py (original) +++ pypy/trunk/pypy/module/cpyext/methodobject.py Tue Jun 1 11:36:50 2010 @@ -125,7 +125,7 @@ self.space = space self.method_name = method_name self.wrapper_func = wrapper_func - assert type(wrapper_func_kwds) is not str + assert not isinstance(wrapper_func_kwds, str) self.wrapper_func_kwds = wrapper_func_kwds self.doc = doc self.func = func From arigo at codespeak.net Tue Jun 1 11:59:18 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 11:59:18 +0200 (CEST) Subject: [pypy-svn] r74996 - pypy/branch/blackhole-improvement/pypy/jit/metainterp/test Message-ID: <20100601095918.8835A282BD8@codespeak.net> Author: arigo Date: Tue Jun 1 11:59:16 2010 New Revision: 74996 Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizeopt.py Log: Raise the "priority" of this test, and write another one with int_is_zero. Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizeopt.py Tue Jun 1 11:59:16 2010 @@ -411,7 +411,7 @@ self.optimize_loop(ops, 'Not', expected) def test_int_is_true_1(self): - py.test.skip("too bad") + py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -428,6 +428,24 @@ """ self.optimize_loop(ops, 'Not', expected) + def test_int_is_true_is_zero(self): + py.test.skip("XXX implement me") + ops = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + expected = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + self.optimize_loop(ops, 'Not', expected) + def test_ooisnull_oononnull_2(self): ops = """ [p0] From arigo at codespeak.net Tue Jun 1 12:07:12 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 12:07:12 +0200 (CEST) Subject: [pypy-svn] r74997 - pypy/branch/blackhole-improvement/pypy/module/pypyjit/test Message-ID: <20100601100712.78698282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 12:07:11 2010 New Revision: 74997 Modified: pypy/branch/blackhole-improvement/pypy/module/pypyjit/test/test_pypy_c.py Log: Increase the numbers. This is due to the fact that we don't generate any more "guard_isnull" for non-gc pointers. There are skipped tests in test_optimizeopt about performing the same kind of guard removal that we do for guard_isnull, but it's not completely trivial. Modified: pypy/branch/blackhole-improvement/pypy/module/pypyjit/test/test_pypy_c.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/module/pypyjit/test/test_pypy_c.py (original) +++ pypy/branch/blackhole-improvement/pypy/module/pypyjit/test/test_pypy_c.py Tue Jun 1 12:07:11 2010 @@ -222,7 +222,7 @@ while i < n+OFFSET: i = f(f(i)) return i - ''', 96, + ''', 98, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOAD_GLOBAL") @@ -263,7 +263,7 @@ x = a.f(i) i = a.f(x) return i - ''', 92, + ''', 93, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOOKUP_METHOD") @@ -308,7 +308,7 @@ x = a.f(i) i = a.g(x) return i - ''', 105, + ''', 106, ([20], 20), ([31], 31)) ops = self.get_by_bytecode("LOOKUP_METHOD") From arigo at codespeak.net Tue Jun 1 12:07:20 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 12:07:20 +0200 (CEST) Subject: [pypy-svn] r74998 - pypy/branch/blackhole-improvement/pypy/jit/codewriter Message-ID: <20100601100720.D6C62282BDB@codespeak.net> Author: arigo Date: Tue Jun 1 12:07:19 2010 New Revision: 74998 Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py Log: Rename. Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py Tue Jun 1 12:07:19 2010 @@ -646,7 +646,7 @@ def _is_gc(self, v): return v.concretetype.TO._gckind == 'gc' - def _rewrite_nongc_ptrs(self, op): + def _rewrite_cmp_ptrs(self, op): if self._is_gc(op.args[0]): return op else: @@ -664,14 +664,14 @@ def rewrite_op_ptr_eq(self, op): op1 = self._rewrite_equality(op, 'ptr_iszero') - return self._rewrite_nongc_ptrs(op1) + return self._rewrite_cmp_ptrs(op1) def rewrite_op_ptr_ne(self, op): op1 = self._rewrite_equality(op, 'ptr_nonzero') - return self._rewrite_nongc_ptrs(op1) + return self._rewrite_cmp_ptrs(op1) - rewrite_op_ptr_iszero = _rewrite_nongc_ptrs - rewrite_op_ptr_nonzero = _rewrite_nongc_ptrs + rewrite_op_ptr_iszero = _rewrite_cmp_ptrs + rewrite_op_ptr_nonzero = _rewrite_cmp_ptrs def rewrite_op_cast_ptr_to_int(self, op): if self._is_gc(op.args[0]): From arigo at codespeak.net Tue Jun 1 12:09:38 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 12:09:38 +0200 (CEST) Subject: [pypy-svn] r74999 - pypy/trunk/pypy/translator/c/src Message-ID: <20100601100938.92F33282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 12:09:37 2010 New Revision: 74999 Modified: pypy/trunk/pypy/translator/c/src/stack.h Log: Attempt to workaround the issue of test_marshal running out of real stack, by increasing the stack limit from 512kb to 768kb. The original value comes from CPython, so it's expected that we consume a bit more stack. Modified: pypy/trunk/pypy/translator/c/src/stack.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/stack.h (original) +++ pypy/trunk/pypy/translator/c/src/stack.h Tue Jun 1 12:09:37 2010 @@ -3,7 +3,7 @@ /*** C header subsection: stack operations ***/ #ifndef MAX_STACK_SIZE -# define MAX_STACK_SIZE (1 << 19) +# define MAX_STACK_SIZE (3 << 18) /* 768 kb */ #endif /* This include must be done in any case to initialise From afa at codespeak.net Tue Jun 1 14:39:12 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 1 Jun 2010 14:39:12 +0200 (CEST) Subject: [pypy-svn] r75000 - pypy/trunk/pypy/rlib Message-ID: <20100601123912.EFFD0282B9C@codespeak.net> Author: afa Date: Tue Jun 1 14:39:10 2010 New Revision: 75000 Modified: pypy/trunk/pypy/rlib/rwin32.py Log: The JIT does not like lltype.malloc(flavor='raw'); hide the function. Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Tue Jun 1 14:39:10 2010 @@ -7,6 +7,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import intmask +from pypy.rlib import jit import os, sys, errno # This module can be imported on any platform, @@ -198,6 +199,7 @@ [lltype.Ptr(OSVERSIONINFO)], DWORD) + @jit.dont_look_inside def GetVersionEx(): info = lltype.malloc(OSVERSIONINFO, flavor='raw') rffi.setintfield(info, 'c_dwOSVersionInfoSize', From fijal at codespeak.net Tue Jun 1 16:15:01 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jun 2010 16:15:01 +0200 (CEST) Subject: [pypy-svn] r75001 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20100601141501.73E2C36C22F@codespeak.net> Author: fijal Date: Tue Jun 1 16:14:59 2010 New Revision: 75001 Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py Log: Revert this change for now, breaks stuff and I can't fix it Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Tue Jun 1 16:14:59 2010 @@ -645,7 +645,7 @@ """ str_chars_offset = (offsetof(STRTYPE, 'chars') + \ itemoffsetof(STRTYPE.chars, 0)) - gc_buf = lltype.nullptr(STRTYPE) # rgc.malloc_nonmovable(STRTYPE, count) + gc_buf = rgc.malloc_nonmovable(STRTYPE, count) if gc_buf: realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset raw_buf = cast(TYPEP, realbuf) From arigo at codespeak.net Tue Jun 1 16:39:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 16:39:34 +0200 (CEST) Subject: [pypy-svn] r75002 - in pypy/trunk/pypy/jit: backend backend/x86 metainterp Message-ID: <20100601143934.5183A282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 16:39:32 2010 New Revision: 75002 Modified: pypy/trunk/pypy/jit/backend/model.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Finish the work on CALL_ASSEMBLER: direct support even if the function did not return an int. Modified: pypy/trunk/pypy/jit/backend/model.py ============================================================================== --- pypy/trunk/pypy/jit/backend/model.py (original) +++ pypy/trunk/pypy/jit/backend/model.py Tue Jun 1 16:39:32 2010 @@ -6,7 +6,10 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Tue Jun 1 16:39:32 2010 @@ -1427,28 +1427,65 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + mc.JMP(rel8_patched_later) # done jmp_location = mc.get_relative_pos() + # + # Path B: load the return value directly from fail_boxes_xxx[0] offset = jmp_location - je_location assert 0 < offset <= 127 mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + # + if op.result is None: + assert result_loc is None + else: + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + elif kind == REF: + adr = self.fail_boxes_ref.get_addr_for_num(0) + else: + raise AssertionError(kind) + mc.MOV(eax, heap(adr)) + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Tue Jun 1 16:39:32 2010 @@ -656,7 +656,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Tue Jun 1 16:39:32 2010 @@ -1126,8 +1126,10 @@ self.__dict__.update(compile.make_done_loop_tokens()) # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) def _freeze_(self): return True From fijal at codespeak.net Tue Jun 1 16:42:08 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jun 2010 16:42:08 +0200 (CEST) Subject: [pypy-svn] r75003 - pypy/trunk/pypy/module/cpyext Message-ID: <20100601144208.08D1B282B9C@codespeak.net> Author: fijal Date: Tue Jun 1 16:42:06 2010 New Revision: 75003 Modified: pypy/trunk/pypy/module/cpyext/methodobject.py Log: remove completely bogus assert Modified: pypy/trunk/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/methodobject.py (original) +++ pypy/trunk/pypy/module/cpyext/methodobject.py Tue Jun 1 16:42:06 2010 @@ -125,7 +125,6 @@ self.space = space self.method_name = method_name self.wrapper_func = wrapper_func - assert not isinstance(wrapper_func_kwds, str) self.wrapper_func_kwds = wrapper_func_kwds self.doc = doc self.func = func From arigo at codespeak.net Tue Jun 1 16:52:46 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 16:52:46 +0200 (CEST) Subject: [pypy-svn] r75004 - pypy/trunk/pypy/jit/backend/x86 Message-ID: <20100601145246.C0AFC282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 16:52:44 2010 New Revision: 75004 Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py Log: Oups. Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Tue Jun 1 16:52:44 2010 @@ -1476,7 +1476,7 @@ if kind == INT: adr = self.fail_boxes_int.get_addr_for_num(0) elif kind == REF: - adr = self.fail_boxes_ref.get_addr_for_num(0) + adr = self.fail_boxes_ptr.get_addr_for_num(0) else: raise AssertionError(kind) mc.MOV(eax, heap(adr)) From getxsick at codespeak.net Tue Jun 1 19:47:38 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 1 Jun 2010 19:47:38 +0200 (CEST) Subject: [pypy-svn] r75006 - in pypy/branch/fast-ctypes/pypy/module/jitffi: . test Message-ID: <20100601174738.0C790282BD8@codespeak.net> Author: getxsick Date: Tue Jun 1 19:47:37 2010 New Revision: 75006 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: first try of a list of arguments. deadly limited, only for integers etc. Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 1 19:47:37 2010 @@ -21,7 +21,11 @@ self.space = space self.cpu = CPU(None, None) - def call(self, space, func, a, b, res_type): # XXX temporary fixed number of func args (ints) + def call(self, space, func, w_func_args, res_type='void'): + # only integers are supported for now + func_args_w = space.listview(w_func_args) + assert isinstance(func_args_w, list) + if res_type == 'int': bres = BoxInt() elif res_type == 'float': @@ -38,21 +42,19 @@ except KeyError: raise operationerrfmt(space.w_ValueError, "Cannot find symbol %s", func) - bfuncaddr = BoxInt(addr) - barg0 = BoxInt(a) - barg1 = BoxInt(b) - FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Signed], - lltype.Signed)) + args_type = [ lltype.Signed for i in func_args_w ] + FPTR = lltype.Ptr(lltype.FuncType(args_type, lltype.Signed)) FUNC = deref(FPTR) calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) - oplist = [ResOperation(rop.CALL, [bfuncaddr, barg0, barg1], bres, - descr=calldescr), + bargs = [ BoxInt(x.intval) for x in func_args_w ] + inputargs = [bfuncaddr] + bargs + + oplist = [ResOperation(rop.CALL, inputargs, bres, descr=calldescr), ResOperation(rop.FINISH, [bres], None, descr=BasicFailDescr(0))] - inputargs = [bfuncaddr, barg0, barg1] looptoken = LoopToken() self.cpu.compile_loop(inputargs, oplist, looptoken) @@ -78,7 +80,7 @@ else: raise ValueError(res_type) return space.wrap(r) - call.unwrap_spec = ['self', ObjSpace, str, int, int, str] + call.unwrap_spec = ['self', ObjSpace, str, W_Root, str] def descr_new_cdll(space, w_type, name): try: Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 1 19:47:37 2010 @@ -19,6 +19,14 @@ { return a+b; } + + int max3(int a, int b, int c) + { + int max = a; + if (b > max) max = b; + if (c > max) max = c; + return max; + } ''' )) @@ -38,14 +46,19 @@ import jitffi lib = jitffi.CDLL(self.lib_name) - res = lib.call('add_integers', 1, 2, 'int') + res = lib.call('add_integers', [1, 2], 'int') assert 3 == res assert isinstance(res, int) - res = lib.call('add_integers', -1, 2, 'int') + res = lib.call('add_integers', [-1, 2], 'int') assert 1 == res - res = lib.call('add_integers', 0, 0, 'int') + res = lib.call('add_integers', [0, 0], 'int') assert 0 == res - res = lib.call('return_float', 1, 2, 'float') + res = lib.call('max3', [2, 8, 3], 'int') + assert 8 == res + + res = lib.call('return_float', [1, 2], 'float') assert 3.0 == res assert isinstance(res, float) + #res = lib.call('return_float', [1.5, 1.2], 'float') + #assert 2.7 == res From arigo at codespeak.net Tue Jun 1 20:36:02 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 20:36:02 +0200 (CEST) Subject: [pypy-svn] r75007 - pypy/branch/x86-64-jit-backend/pypy/jit/metainterp Message-ID: <20100601183602.96180282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 20:36:01 2010 New Revision: 75007 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py Log: Fix the commented out print. Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py Tue Jun 1 20:36:01 2010 @@ -987,7 +987,7 @@ while True: pc = self.pc op = ord(self.bytecode[pc]) - #print self.metainterp.opcode_names[op] + #print self.jitcode.name, self.metainterp.staticdata.opcode_names[op] self.pc = pc + 1 staticdata = self.metainterp.staticdata stop = staticdata.opcode_implementations[op](self, pc) From getxsick at codespeak.net Tue Jun 1 20:53:07 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 1 Jun 2010 20:53:07 +0200 (CEST) Subject: [pypy-svn] r75008 - pypy/branch/fast-ctypes/pypy/module/jitffi/test Message-ID: <20100601185307.F2F74282B9C@codespeak.net> Author: getxsick Date: Tue Jun 1 20:53:06 2010 New Revision: 75008 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: remove unneeded glibc for now Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 1 20:53:06 2010 @@ -36,11 +36,9 @@ return str(platform.compile([c_file], eci, 'x', standalone=False)) def setup_class(cls): - from pypy.rlib.libffi import get_libc_name space = gettestobjspace(usemodules=('jitffi',)) cls.space = space cls.w_lib_name = space.wrap(cls.preprare_c_example()) - cls.w_libc_name = space.wrap(get_libc_name()) def test_call(self): import jitffi From jcreigh at codespeak.net Tue Jun 1 21:36:04 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 1 Jun 2010 21:36:04 +0200 (CEST) Subject: [pypy-svn] r75009 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100601193604.64172282B9C@codespeak.net> Author: jcreigh Date: Tue Jun 1 21:36:02 2010 New Revision: 75009 Added: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: add hack to encode the immediates of instructions with 16-bit operands correctly Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Tue Jun 1 21:36:02 2010 @@ -178,6 +178,17 @@ return INSN + def _16_bit_binaryop(name): + def INSN(self, loc1, loc2): + # Select 16-bit operand mode + self.writechar('\x66') + # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding + self._use_16_bit_immediate = True + getattr(self, name)(loc1, loc2) + self._use_16_bit_immediate = False + + return INSN + AND = _binaryop('AND') OR = _binaryop('OR') XOR = _binaryop('XOR') @@ -193,8 +204,10 @@ NEG = _unaryop('NEG') CMP = _binaryop('CMP') + CMP16 = _16_bit_binaryop('CMP') MOV = _binaryop('MOV') MOV8 = _binaryop('MOV8') + MOV16 = _16_bit_binaryop('MOV') MOVZX8 = _binaryop('MOVZX8') MOVZX16 = _binaryop('MOVZX16') @@ -214,16 +227,6 @@ CALL = _unaryop('CALL') - def MOV16(self, dest_loc, src_loc): - # Select 16-bit operand mode - self.writechar('\x66') - self.MOV(dest_loc, src_loc) - - def CMP16(self, a_loc, b_loc): - # Select 16-bit operand mode - self.writechar('\x66') - self.CMP(a_loc, b_loc) - def imm(x): # XXX: ri386 migration shim if isinstance(x, ConstInt): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Tue Jun 1 21:36:02 2010 @@ -116,7 +116,10 @@ elif width == 'q' and mc.WORD == 8: mc.writeimm64(immediate) else: - mc.writeimm32(immediate) + if mc._use_16_bit_immediate: + mc.writeimm16(immediate) + else: + mc.writeimm32(immediate) return 0 def immediate(argnum, width='i'): @@ -385,6 +388,9 @@ class AbstractX86CodeBuilder(object): """Abstract base class.""" + # Used by the 16-bit version of instructions + _use_16_bit_immediate = False + def writechar(self, char): raise NotImplementedError Added: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py ============================================================================== --- (empty file) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Tue Jun 1 21:36:02 2010 @@ -0,0 +1,15 @@ +from pypy.jit.backend.x86.regloc import * +from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, assert_encodes_as + +class LocationCodeBuilder32(CodeBuilder32, LocationCodeBuilder): + pass + +cb32 = LocationCodeBuilder32 + +def test_mov_16(): + assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') + assert_encodes_as(cb32, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') + +def test_cmp_16(): + assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') + assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') From arigo at codespeak.net Tue Jun 1 21:54:15 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 21:54:15 +0200 (CEST) Subject: [pypy-svn] r75010 - pypy/trunk/pypy/translator/backendopt/test Message-ID: <20100601195415.8C060282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 21:54:13 2010 New Revision: 75010 Modified: pypy/trunk/pypy/translator/backendopt/test/test_storesink.py Log: A test. Modified: pypy/trunk/pypy/translator/backendopt/test/test_storesink.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_storesink.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_storesink.py Tue Jun 1 21:54:13 2010 @@ -2,6 +2,7 @@ import py from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.storesink import storesink_graph +from pypy.translator.backendopt import removenoops from pypy.objspace.flow.model import last_exception, checkgraph from pypy.conftest import option @@ -19,6 +20,7 @@ t = self.translate(f, argtypes) getfields = 0 graph = graphof(t, f) + removenoops.remove_same_as(graph) checkgraph(graph) storesink_graph(graph) checkgraph(graph) @@ -119,3 +121,17 @@ return one + two self.check(f, [int], 2) + + def test_bug_1(self): + class A(object): + pass + + def f(i): + a = A() + a.cond = i > 0 + n = a.cond + if a.cond: + return True + return n + + self.check(f, [int], 1) From arigo at codespeak.net Tue Jun 1 21:59:43 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 21:59:43 +0200 (CEST) Subject: [pypy-svn] r75011 - pypy/trunk/pypy/translator/backendopt Message-ID: <20100601195943.D5D19282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 21:59:42 2010 New Revision: 75011 Modified: pypy/trunk/pypy/translator/backendopt/storesink.py Log: Fix r75010: don't rename manually -- we forgot to rename the exitswitch. Instead, just put 'same_as' and let the renaming be handled by existing code. Modified: pypy/trunk/pypy/translator/backendopt/storesink.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/storesink.py (original) +++ pypy/trunk/pypy/translator/backendopt/storesink.py Tue Jun 1 21:59:42 2010 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem.lloperation import llop +from pypy.translator.backendopt import removenoops def has_side_effects(op): if op.opname == 'debug_assert': @@ -10,30 +11,27 @@ return True def storesink_graph(graph): - def rename(op, renaming): - for i, arg in enumerate(op.args): - r = renaming.get(arg, None) - if r is not None: - op.args[i] = r - return op def clear_cache_for(cache, concretetype, fieldname): for k in cache.keys(): if k[0].concretetype == concretetype and k[1] == fieldname: del cache[k] + + added_some_same_as = False for block in graph.iterblocks(): newops = [] cache = {} - renaming = {} for op in block.operations: if op.opname == 'getfield': tup = (op.args[0], op.args[1].value) res = cache.get(tup, None) if res is not None: - renaming[op.result] = res - continue - cache[tup] = op.result + op.opname = 'same_as' + op.args = [res] + added_some_same_as = True + else: + cache[tup] = op.result elif op.opname in ['setarrayitem', 'setinteriorfield']: pass elif op.opname == 'setfield': @@ -41,9 +39,9 @@ op.args[1].value) elif has_side_effects(op): cache = {} - newops.append(rename(op, renaming)) + newops.append(op) if block.operations: block.operations = newops - for exit in block.exits: - rename(exit, renaming) - + + if added_some_same_as: + removenoops.remove_same_as(graph) From arigo at codespeak.net Tue Jun 1 22:08:42 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 22:08:42 +0200 (CEST) Subject: [pypy-svn] r75012 - pypy/trunk/pypy/jit/backend/x86 Message-ID: <20100601200842.9087936C230@codespeak.net> Author: arigo Date: Tue Jun 1 22:08:41 2010 New Revision: 75012 Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py Log: Re-oups. :-( Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Tue Jun 1 22:08:41 2010 @@ -1433,12 +1433,15 @@ tmp=eax) mc = self._start_block() if op.result is None: + assert result_loc is None value = self.cpu.done_with_this_frame_void_v else: kind = op.result.type if kind == INT: + assert result_loc is eax value = self.cpu.done_with_this_frame_int_v elif kind == REF: + assert result_loc is eax value = self.cpu.done_with_this_frame_ref_v elif kind == FLOAT: value = self.cpu.done_with_this_frame_float_v @@ -1454,17 +1457,15 @@ if isinstance(result_loc, MODRM64): mc.FSTP(result_loc) #else: result_loc is already either eax or None, checked below - mc.JMP(rel8_patched_later) # done - jmp_location = mc.get_relative_pos() - # - # Path B: load the return value directly from fail_boxes_xxx[0] - offset = jmp_location - je_location - assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) - # - if op.result is None: - assert result_loc is None - else: + if op.result is not None: + mc.JMP(rel8_patched_later) # done + jmp_location = mc.get_relative_pos() + # + # Path B: load the return value directly from fail_boxes_xxx[0] + offset = jmp_location - je_location + assert 0 < offset <= 127 + mc.overwrite(je_location - 1, [chr(offset)]) + # kind = op.result.type if kind == FLOAT: xmmtmp = X86XMMRegisterManager.all_regs[0] @@ -1475,11 +1476,17 @@ assert result_loc is eax if kind == INT: adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) elif kind == REF: adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) else: raise AssertionError(kind) - mc.MOV(eax, heap(adr)) + else: + # in that case, don't generate a JMP at all, + # because "Path B" is empty + jmp_location = je_location # # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location From arigo at codespeak.net Tue Jun 1 22:20:10 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 22:20:10 +0200 (CEST) Subject: [pypy-svn] r75013 - pypy/trunk/pypy/translator/tool Message-ID: <20100601202010.956D536C230@codespeak.net> Author: arigo Date: Tue Jun 1 22:20:09 2010 New Revision: 75013 Modified: pypy/trunk/pypy/translator/tool/cbuild.py Log: Avoid writing absolute paths in the Makefile. Modified: pypy/trunk/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/cbuild.py Tue Jun 1 22:20:09 2010 @@ -276,13 +276,15 @@ if host.name.startswith('darwin'): for sym in self.export_symbols: f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) + d['link_extra'] += ("-Wl,-exported_symbols_list,../" + + file_name.basename, ) else: f.write("{\n") for sym in self.export_symbols: f.write("%s;\n" % (sym,)) f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) + d['link_extra'] += ("-Wl,--export-dynamic,--version-script=../" + + file_name.basename, ) f.close() d['export_symbols'] = () return ExternalCompilationInfo(**d) From arigo at codespeak.net Tue Jun 1 22:49:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jun 2010 22:49:34 +0200 (CEST) Subject: [pypy-svn] r75014 - pypy/trunk/pypy/translator/tool Message-ID: <20100601204934.BDB7A282B9C@codespeak.net> Author: arigo Date: Tue Jun 1 22:49:32 2010 New Revision: 75014 Modified: pypy/trunk/pypy/translator/tool/cbuild.py Log: Revert r75013. It's a mess because we don't know if the current directory is /tmp/usession-xxx/testing_1 or /tmp/usession-xxx itself. Modified: pypy/trunk/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/cbuild.py Tue Jun 1 22:49:32 2010 @@ -276,15 +276,13 @@ if host.name.startswith('darwin'): for sym in self.export_symbols: f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,../" + - file_name.basename, ) + d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) else: f.write("{\n") for sym in self.export_symbols: f.write("%s;\n" % (sym,)) f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=../" + - file_name.basename, ) + d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) f.close() d['export_symbols'] = () return ExternalCompilationInfo(**d) From jcreigh at codespeak.net Tue Jun 1 23:05:06 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 1 Jun 2010 23:05:06 +0200 (CEST) Subject: [pypy-svn] r75015 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend: . x86 Message-ID: <20100601210506.591F4282B9C@codespeak.net> Author: jcreigh Date: Tue Jun 1 23:05:04 2010 New Revision: 75015 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/detect_cpu.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Log: add skeleton CPU_x86_64 class Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/detect_cpu.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/detect_cpu.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/detect_cpu.py Tue Jun 1 23:05:04 2010 @@ -56,6 +56,8 @@ return "pypy.jit.backend.x86.runner", "CPU" elif backend_name == 'x86-without-sse2': return "pypy.jit.backend.x86.runner", "CPU386_NO_SSE2" + elif backend_name == 'x86_64': + return "pypy.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "pypy.jit.backend.cli.runner", "CliCPU" elif backend_name == 'llvm': Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Tue Jun 1 23:05:04 2010 @@ -7,7 +7,7 @@ from pypy.jit.backend.x86.profagent import ProfileAgent from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU -class CPU386(AbstractLLCPU): +class AbstractX86CPU(AbstractLLCPU): debug = True supports_floats = True @@ -129,10 +129,14 @@ assert fail_index == fail_index_2 return faildescr +class CPU386(AbstractX86CPU): + pass class CPU386_NO_SSE2(CPU386): supports_floats = False +class CPU_X86_64(AbstractX86CPU): + pass CPU = CPU386 From jcreigh at codespeak.net Tue Jun 1 23:40:46 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 1 Jun 2010 23:40:46 +0200 (CEST) Subject: [pypy-svn] r75016 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100601214046.7A122282B9C@codespeak.net> Author: jcreigh Date: Tue Jun 1 23:40:45 2010 New Revision: 75016 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py Log: clean up how instructions which must be manually tested are skipped in test_rx86_(32|64)_auto_encoding.py Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Tue Jun 1 23:40:45 2010 @@ -655,39 +655,6 @@ AbstractX86CodeBuilder.MOV_ri(self, R.eax, target) AbstractX86CodeBuilder.CALL_r(self, R.eax) - # unsupported -- must use e.g. MOV tmpreg, immed64; MOV reg, [tmpreg] - def MOV_rj(self, reg, mem_immed): - py.test.skip("MOV_rj unsupported") - def MOV_jr(self, mem_immed, reg): - py.test.skip("MOV_jr unsupported") - def MOV_ji(self, mem_immed, immed): - py.test.skip("MOV_ji unsupported") - def XCHG_rj(self, reg, mem_immed): - py.test.skip("XCGH_rj unsupported") - def CMP_ji(self, addr, immed): - py.test.skip("CMP_ji unsupported") - def CMP_rj(self, reg, immed): - py.test.skip("CMP_rj unsupported") - def MOVSD_xj(self, xmm_reg, mem_immed): - py.test.skip("MOVSD_rj unsupported") - def MOVSD_jx(self, xmm_reg, mem_immed): - py.test.skip("MOVSD_jr unsupported") - def ADDSD_xj(self, xmm_reg, mem_immed): - py.test.skip("ADDSD_rj unsupported") - def SUBSD_xj(self, xmm_reg, mem_immed): - py.test.skip("SUBSD_rj unsupported") - def MULSD_xj(self, xmm_reg, mem_immed): - py.test.skip("MULSD_rj unsupported") - def DIVSD_xj(self, xmm_reg, mem_immed): - py.test.skip("DIVSD_rj unsupported") - def UCOMISD_xj(self, xmm_reg, mem_immed): - py.test.skip("UCOMISD_rj unsupported") - def ANDPD_xj(self, xmm_reg, mem_immed): - py.test.skip("ANDPD_rj unsupported") - def XORPD_xj(self, xmm_reg, mem_immed): - py.test.skip("XORPD_rj unsupported") - - # ____________________________________________________________ all_instructions = [name for name in AbstractX86CodeBuilder.__dict__ Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py Tue Jun 1 23:40:45 2010 @@ -230,16 +230,6 @@ return [] # MOV EAX, [immediate]: there is a special encoding if methname == 'MOV_jr' and args[1] == rx86.R.eax: return [] # MOV [immediate], EAX: there is a special encoding - if methname == 'SET_ir': - py.test.skip("SET_ir: must be tested manually") - if methname.startswith('SHL') or methname.startswith('SAR') or methname.startswith('SHR'): - # XXX: Would be nice to test these automatically - py.test.skip('Shifts must be tested manually') - if methname == 'FSTP_b': - # Doesn't work on 64-bit, skipping for now - py.test.skip('Skipping FSTP') - if methname == 'CALL_j': - py.test.skip("CALL_j is actually relative") return [args] @@ -248,13 +238,28 @@ pass return X86_CodeBuilder + def should_skip_instruction(self, instrname, argmodes): + is_artificial_instruction = instrname[-1].isdigit() or (argmodes != '' and argmodes[-1].isdigit()) + return ( + is_artificial_instruction or + # XXX: Can't tests shifts automatically at the moment + (instrname[:3] in ('SHL', 'SAR', 'SHR')) or + # CALL_j is actually relative, so tricky to test + (instrname == 'CALL' and argmodes == 'j') or + # SET_ir must be tested manually + (instrname == 'SET' and argmodes == 'ir') + ) + + + def complete_test(self, methname): if '_' in methname: instrname, argmodes = methname.split('_') else: instrname, argmodes = methname, '' - if instrname[-1].isdigit() or (argmodes != '' and argmodes[-1].isdigit()): - print "artificial instruction: %r" % (methname,) + + if self.should_skip_instruction(instrname, argmodes): + print "Skipping %s" % methname return print "Testing %s with argmodes=%r" % (instrname, argmodes) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py Tue Jun 1 23:40:45 2010 @@ -15,6 +15,14 @@ rx86.R.r8, rx86.R.r9, rx86.R.r10, rx86.R.r11, rx86.R.r12, rx86.R.r13, rx86.R.r14, rx86.R.r15] + def should_skip_instruction(self, instrname, argmodes): + return ( + super(TestRx86_64, self).should_skip_instruction(instrname, argmodes) or + ('j' in argmodes) or + # Not testing FSTP on 64-bit for now + (instrname == 'FSTP') + ) + def array_tests(self): # reduce a little bit -- we spend too long in these tests lst = super(TestRx86_64, self).array_tests() From arigo at codespeak.net Wed Jun 2 17:27:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jun 2010 17:27:50 +0200 (CEST) Subject: [pypy-svn] r75020 - pypy/branch/blackhole-improvement/pypy/jit/backend/test Message-ID: <20100602152750.1BC4C282BD4@codespeak.net> Author: arigo Date: Wed Jun 2 17:27:48 2010 New Revision: 75020 Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_random.py Log: Fix. Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_random.py Wed Jun 2 17:27:48 2010 @@ -20,8 +20,6 @@ class FakeMetaInterp(object): def execute_raised(self, exc, constant=False): self._got_exc = exc - def execute_did_not_raise(self): - self._got_exc = None class OperationBuilder(object): def __init__(self, cpu, loop, vars): @@ -47,6 +45,7 @@ return fork def do(self, opnum, argboxes, descr=None): + self.fakemetainterp._got_exc = None v_result = execute_nonspec(self.cpu, self.fakemetainterp, opnum, argboxes, descr) if isinstance(v_result, Const): @@ -285,7 +284,6 @@ builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_OVERFLOW, [], None) - del builder.fakemetainterp._got_exc op.descr = BasicFailDescr() op.fail_args = fail_subset builder.loop.operations.append(op) From arigo at codespeak.net Wed Jun 2 21:17:01 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jun 2010 21:17:01 +0200 (CEST) Subject: [pypy-svn] r75023 - in pypy/trunk/pypy/jit: backend backend/x86 metainterp Message-ID: <20100602191701.0652F282BD4@codespeak.net> Author: arigo Date: Wed Jun 2 21:16:59 2010 New Revision: 75023 Modified: pypy/trunk/pypy/jit/backend/model.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Revert r75002, r75004 and r75012. Until I find out why, for now it gives crashes. Modified: pypy/trunk/pypy/jit/backend/model.py ============================================================================== --- pypy/trunk/pypy/jit/backend/model.py (original) +++ pypy/trunk/pypy/jit/backend/model.py Wed Jun 2 21:16:59 2010 @@ -6,10 +6,7 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None - done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 - done_with_this_frame_ref_v = -1 - done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Wed Jun 2 21:16:59 2010 @@ -1427,72 +1427,28 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) - # - # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - if op.result is None: - assert result_loc is None - value = self.cpu.done_with_this_frame_void_v - else: - kind = op.result.type - if kind == INT: - assert result_loc is eax - value = self.cpu.done_with_this_frame_int_v - elif kind == REF: - assert result_loc is eax - value = self.cpu.done_with_this_frame_ref_v - elif kind == FLOAT: - value = self.cpu.done_with_this_frame_float_v - else: - raise AssertionError(kind) - mc.CMP(eax, imm(value)) - mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' + mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) + mc.JE(rel8_patched_later) je_location = mc.get_relative_pos() - # - # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - if isinstance(result_loc, MODRM64): - mc.FSTP(result_loc) - #else: result_loc is already either eax or None, checked below - if op.result is not None: - mc.JMP(rel8_patched_later) # done - jmp_location = mc.get_relative_pos() - # - # Path B: load the return value directly from fail_boxes_xxx[0] - offset = jmp_location - je_location - assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) - # - kind = op.result.type - if kind == FLOAT: - xmmtmp = X86XMMRegisterManager.all_regs[0] - adr = self.fail_boxes_float.get_addr_for_num(0) - mc.MOVSD(xmmtmp, heap64(adr)) - mc.MOVSD(result_loc, xmmtmp) - else: - assert result_loc is eax - if kind == INT: - adr = self.fail_boxes_int.get_addr_for_num(0) - mc.MOV(eax, heap(adr)) - elif kind == REF: - adr = self.fail_boxes_ptr.get_addr_for_num(0) - mc.XOR(eax, eax) - mc.XCHG(eax, heap(adr)) - else: - raise AssertionError(kind) - else: - # in that case, don't generate a JMP at all, - # because "Path B" is empty - jmp_location = je_location - # - # Here we join Path A and Path B again + mc.JMP(rel8_patched_later) + jmp_location = mc.get_relative_pos() + offset = jmp_location - je_location + assert 0 < offset <= 127 + mc.overwrite(je_location - 1, [chr(offset)]) + mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) offset = mc.get_relative_pos() - jmp_location assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() + if isinstance(result_loc, MODRM64): + self.mc.FSTP(result_loc) + else: + assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Wed Jun 2 21:16:59 2010 @@ -656,7 +656,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index >= 0: + if vable_index != -1: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Wed Jun 2 21:16:59 2010 @@ -1126,10 +1126,8 @@ self.__dict__.update(compile.make_done_loop_tokens()) # store this information for fastpath of call_assembler - name = self.result_type - tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) - num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) - setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + d = self.loop_tokens_done_with_this_frame_int[0].finishdescr + self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) def _freeze_(self): return True From fijal at codespeak.net Wed Jun 2 22:49:00 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jun 2010 22:49:00 +0200 (CEST) Subject: [pypy-svn] r75024 - pypy/branch/unfreeze-encodings Message-ID: <20100602204900.E7F3F282BD4@codespeak.net> Author: fijal Date: Wed Jun 2 22:48:58 2010 New Revision: 75024 Added: pypy/branch/unfreeze-encodings/ (props changed) - copied from r75023, pypy/trunk/ Log: A branch to try to unfreeze encodings From getxsick at codespeak.net Wed Jun 2 23:27:59 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Wed, 2 Jun 2010 23:27:59 +0200 (CEST) Subject: [pypy-svn] r75025 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100602212759.55FB5282BD4@codespeak.net> Author: getxsick Date: Wed Jun 2 23:27:57 2010 New Revision: 75025 Removed: pypy/branch/fast-ctypes/pypy/module/jitffi/ Log: kill pypy/module/jitffi for now From getxsick at codespeak.net Wed Jun 2 23:29:51 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Wed, 2 Jun 2010 23:29:51 +0200 (CEST) Subject: [pypy-svn] r75026 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100602212951.6E29D282BD4@codespeak.net> Author: getxsick Date: Wed Jun 2 23:29:50 2010 New Revision: 75026 Added: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (contents, props changed) pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (contents, props changed) Log: add pypy/rlib/jitffi module Added: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- (empty file) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Wed Jun 2 23:29:50 2010 @@ -0,0 +1,79 @@ +from pypy.interpreter.error import operationerrfmt +from pypy.interpreter.gateway import interp2app +from pypy.interpreter.typedef import TypeDef +from pypy.rlib import rdynload +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.jit.backend.x86.runner import CPU +from pypy.jit.metainterp.history import LoopToken, BasicFailDescr +from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.metainterp.typesystem import deref + +class CDLL(object): + def __init__(self, name): + try: + self.lib = rdynload.dlopen(name) + except libffi.DLOpenError, e: + raise operationerrfmt(space.w_OSError, '%s: %s', name, + e.msg or 'unspecified error') + self.name = name + self.cpu = CPU(None, None) + + def call(self, func, func_args, res_type='void'): + # only integers are supported for now + assert isinstance(func_args, list) + + if res_type == 'int': + bres = BoxInt() + elif res_type == 'float': + bres = BoxFloat() + elif res_type == 'ref': + bres = BoxPtr() + elif res_type == 'void': + bres = None + else: + raise ValueError(res_type) + + try: + addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func)) + except KeyError: + raise operationerrfmt(space.w_ValueError, + "Cannot find symbol %s", func) + bfuncaddr = BoxInt(addr) + + args_type = [ lltype.Signed for i in func_args ] + FPTR = lltype.Ptr(lltype.FuncType(args_type, lltype.Signed)) + FUNC = deref(FPTR) + calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) + + bargs = [ BoxInt(x) for x in func_args ] + inputargs = [bfuncaddr] + bargs + + oplist = [ResOperation(rop.CALL, inputargs, bres, descr=calldescr), + ResOperation(rop.FINISH, [bres], None, + descr=BasicFailDescr(0))] + looptoken = LoopToken() + self.cpu.compile_loop(inputargs, oplist, looptoken) + + i = 0 + for box in inputargs: + self.cpu.set_future_value_int(i, box.getint()) + i += 1 + + res = self.cpu.execute_token(looptoken) + if res is oplist[-1].descr: + self.guard_failed = False + else: + self.guard_failed = True + + if res_type == 'int': + r = BoxInt(self.cpu.get_latest_value_int(0)).getint() + elif res_type == 'float': + r = BoxFloat(self.cpu.get_latest_value_float(0)).getfloat() + elif res_type == 'ref': + r = BoxPtr(self.cpu.get_latest_value_ref(0)).getref() + elif res_type == 'void': + r = None + else: + raise ValueError(res_type) + return r Added: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- (empty file) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Wed Jun 2 23:29:50 2010 @@ -0,0 +1,64 @@ +#from pypy.conftest import gettestobjspace +from pypy.rlib import jitffi +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.platform import platform + +import py + +class TestJitffi(object): + @staticmethod + def preprare_c_example(): + from pypy.tool.udir import udir + c_file = udir.ensure("test_jitffi", dir=True).join("xlib.c") + c_file.write(py.code.Source(''' + int add_integers(int a, int b) + { + return a+b; + } + + float return_float(int a, int b) + { + return a+b; + } + + int max3(int a, int b, int c) + { + int max = a; + if (b > max) max = b; + if (c > max) max = c; + return max; + } + ''' + )) + + symbols = ["add_integers"] + eci = ExternalCompilationInfo(export_symbols=symbols) + + return str(platform.compile([c_file], eci, 'x', standalone=False)) + + def setup_class(cls): + #space = gettestobjspace(usemodules=('jitffi',)) + #cls.space = space + #cls.w_lib_name = space.wrap(cls.preprare_c_example()) + cls.lib_name = cls.preprare_c_example() + + def test_call(self): + lib = jitffi.CDLL(self.lib_name) + + res = lib.call('add_integers', [1, 2], 'int') + assert 3 == res + assert isinstance(res, int) + res = lib.call('add_integers', [-1, 2], 'int') + assert 1 == res + res = lib.call('add_integers', [0, 0], 'int') + assert 0 == res + + res = lib.call('max3', [2, 8, 3], 'int') + assert 8 == res + + res = lib.call('return_float', [1, 2], 'float') + assert 3.0 == res + assert isinstance(res, float) + #res = lib.call('return_float', [1.5, 1.2], 'float') + #assert 2.7 == res + From getxsick at codespeak.net Wed Jun 2 23:31:11 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Wed, 2 Jun 2010 23:31:11 +0200 (CEST) Subject: [pypy-svn] r75027 - pypy/branch/fast-ctypes/pypy/rlib/test Message-ID: <20100602213111.62CEF282BD4@codespeak.net> Author: getxsick Date: Wed Jun 2 23:31:10 2010 New Revision: 75027 Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: remove comments Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Wed Jun 2 23:31:10 2010 @@ -1,4 +1,3 @@ -#from pypy.conftest import gettestobjspace from pypy.rlib import jitffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform @@ -37,9 +36,6 @@ return str(platform.compile([c_file], eci, 'x', standalone=False)) def setup_class(cls): - #space = gettestobjspace(usemodules=('jitffi',)) - #cls.space = space - #cls.w_lib_name = space.wrap(cls.preprare_c_example()) cls.lib_name = cls.preprare_c_example() def test_call(self): From afa at codespeak.net Wed Jun 2 23:58:03 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 2 Jun 2010 23:58:03 +0200 (CEST) Subject: [pypy-svn] r75028 - pypy/trunk/pypy/module/cpyext/patches Message-ID: <20100602215803.6CEF0282BD4@codespeak.net> Author: afa Date: Wed Jun 2 23:58:01 2010 New Revision: 75028 Added: pypy/trunk/pypy/module/cpyext/patches/boost.patch (contents, props changed) Log: The patch I use to compile Boost.Python. This one is against boost version 1.43.0, but it should also apply to other versions. The change in wrapper.cpp is has been proposed to Boost: https://svn.boost.org/trac/boost/ticket/4125 Added: pypy/trunk/pypy/module/cpyext/patches/boost.patch ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/cpyext/patches/boost.patch Wed Jun 2 23:58:01 2010 @@ -0,0 +1,63 @@ +Index: libs/python/src/object/class.cpp +=================================================================== +--- libs/python/src/object/class.cpp 2009-11-13 01:40:01 +0100 ++++ libs/python/src/object/class.cpp 2010-06-02 23:25:08 +0200 +@@ -195,7 +195,7 @@ + + namespace objects + { +-#if PY_VERSION_HEX < 0x03000000 ++#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) + // XXX Not sure why this run into compiling error in Python 3 + extern "C" + { +Index: libs/python/src/object/function.cpp +=================================================================== +--- libs/python/src/object/function.cpp 2010-04-04 07:19:57 +0200 ++++ libs/python/src/object/function.cpp 2010-06-02 23:26:12 +0200 +@@ -435,7 +435,7 @@ + function* new_func = downcast(attribute.ptr()); + PyObject* dict = 0; + +-#if PY_VERSION_HEX < 0x03000000 ++#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) + // Old-style class gone in Python 3 + if (PyClass_Check(ns)) + dict = ((PyClassObject*)ns)->cl_dict; +Index: libs/python/src/wrapper.cpp +=================================================================== +--- libs/python/src/wrapper.cpp 2008-03-22 22:45:55 +0100 ++++ libs/python/src/wrapper.cpp 2010-06-02 23:27:44 +0200 +@@ -25,7 +25,7 @@ + + if ( + PyMethod_Check(m.get()) +- && ((PyMethodObject*)m.get())->im_self == this->m_self ++ && PyMethod_GET_SELF(m.get()) == this->m_self + && class_object->tp_dict != 0 + ) + { +@@ -34,7 +34,7 @@ + + + } +- if (borrowed_f != ((PyMethodObject*)m.get())->im_func) ++ if (borrowed_f != PyMethod_GET_FUNCTION(m.get())) + return override(m); + } + } +Index: tools/build/v2/user-config.jam +=================================================================== +--- tools/build/v2/user-config.jam 2008-07-15 15:53:41 +0200 ++++ tools/build/v2/user-config.jam 2010-06-02 23:46:13 +0200 +@@ -84,3 +84,9 @@ + + # Configure with an explicit installation prefix. + # using qt : /usr/opt/qt ; ++ ++using python : 2.5 ++ : /home/amaury/trunk/pypy/pypy-c ++ : /home/amaury/trunk/pypy/module/cpyext/include ++ /home/amaury/trunk/pypy/_interfaces ++ ; + From arigo at codespeak.net Thu Jun 3 00:06:54 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 00:06:54 +0200 (CEST) Subject: [pypy-svn] r75029 - pypy/trunk/pypy/translator/benchmark Message-ID: <20100602220654.79A02282BD4@codespeak.net> Author: arigo Date: Thu Jun 3 00:06:53 2010 New Revision: 75029 Modified: pypy/trunk/pypy/translator/benchmark/benchmarks.py Log: Use our local copy of templess. Modified: pypy/trunk/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/trunk/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/trunk/pypy/translator/benchmark/benchmarks.py Thu Jun 3 00:06:53 2010 @@ -85,8 +85,9 @@ def run_templess(executable, sizefactor=1): """ run some script in the templess package - templess is some simple templating language, to check out use - 'svn co -r100 http://johnnydebris.net/templess/trunk templess' + templess is some simple templating language. + We have a copy at + 'http://codespeak.net/svn/user/arigo/hack/pypy-hack/templess' """ here = py.path.local(__file__).dirpath() pypath = os.path.dirname(os.path.dirname(py.__file__)) @@ -107,8 +108,7 @@ def check_templess(): return external_dependency('templess', - 'http://johnnydebris.net/templess/trunk', - 100) + 'http://codespeak.net/svn/user/arigo/hack/pypy-hack/templess') def run_gadfly(executable, sizefactor=1): """ run some tests in the gadfly pure Python database """ From afa at codespeak.net Thu Jun 3 00:10:34 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 00:10:34 +0200 (CEST) Subject: [pypy-svn] r75030 - pypy/branch/cpyext-init-cleanup Message-ID: <20100602221034.28DED282BD4@codespeak.net> Author: afa Date: Thu Jun 3 00:10:32 2010 New Revision: 75030 Added: pypy/branch/cpyext-init-cleanup/ (props changed) - copied from r75029, pypy/trunk/ Log: A branch to clarify the mess in the different objects exposed by the API From fijal at codespeak.net Thu Jun 3 00:13:38 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 00:13:38 +0200 (CEST) Subject: [pypy-svn] r75032 - pypy/build/bot2/pypybuildbot Message-ID: <20100602221338.40F6C282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 00:13:37 2010 New Revision: 75032 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: These days we have only one way to run benchmarks Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Thu Jun 3 00:13:37 2010 @@ -116,7 +116,7 @@ "--pypy=pypy/translator/goal/pypy-c", "--resultlog=pypyjit.log", "pypy/module/pypyjit/test"], - logfiles={'pytestLog': 'pypyjit.log'})) + logfiles={'pytestLog': 'pypyjit.log'})) self.addStep(ShellCmd( description="compress pypy-c", command=["bzip2", "-kf", "pypy/translator/goal/pypy-c"])) @@ -147,7 +147,7 @@ self.addStep(Translate(['-Ojit'], [])) pypy_c_rel = "../build/pypy/translator/goal/pypy-c" self.addStep(ShellCmd( - description="run more benchmarks on top of pypy-c-jit", + description="run benchmarks on top of pypy-c-jit", command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', pypy_c_rel, '--upload', '--force-host', 'bigdog', @@ -161,7 +161,7 @@ masterdest=WithProperties(resfile), workdir=".")) self.addStep(ShellCmd( - description="run more benchmarks on top of pypy-c no jit", + description="run benchmarks on top of pypy-c no jit", command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', '../build/pypy/translator/goal/pypy-c', '--revision', WithProperties('%(got_revision)s'), @@ -176,7 +176,7 @@ workdir=".")) self.addStep(ShellCmd( - description="run benchmarks on top of python with psyco", + description="run on top of python with psyco", command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', 'psyco/python_with_psyco.sh', '--revision', WithProperties('%(got_revision)s'), @@ -185,8 +185,3 @@ ], workdir='./benchmarks', haltOnFailure=True)) - - self.addStep(ShellCmd( - description="run benchmarks 1", - command=["python", "pypy/translator/benchmark/jitbench.py", - "pypy/translator/goal/pypy-c"])) From fijal at codespeak.net Thu Jun 3 00:22:32 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 00:22:32 +0200 (CEST) Subject: [pypy-svn] r75033 - pypy/branch/unfreeze-encodings/pypy/module/_codecs Message-ID: <20100602222232.65271282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 00:22:30 2010 New Revision: 75033 Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Log: This is the state I would like to achieve (breaks translation) Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Thu Jun 3 00:22:30 2010 @@ -52,6 +52,9 @@ return replace, newpos return unicode_call_errorhandler + def _freeze_(self): + assert not self.codec_search_path + return False def register_codec(space, w_search_function): """register(search_function) From getxsick at codespeak.net Thu Jun 3 00:32:39 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 3 Jun 2010 00:32:39 +0200 (CEST) Subject: [pypy-svn] r75034 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100602223239.3D812282BD4@codespeak.net> Author: getxsick Date: Thu Jun 3 00:32:33 2010 New Revision: 75034 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: add the Get class. it's used for declaration of function. also it can call the function. still very limited Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Thu Jun 3 00:32:33 2010 @@ -77,3 +77,100 @@ else: raise ValueError(res_type) return r + + def get(self, func, args_type, res_type='void'): + return _Get(self.cpu, self.lib, func, args_type, res_type) + +class _Get(object): + def __init__(self, cpu, lib, func, args_type, res_type='void'): + assert isinstance(args_type, list) + if 'void' in args_type and len(args_type) > 1: + raise ValueError("'void' must be the only parameter") + self.args_type = args_type + self.res_type = res_type + self.cpu = cpu + self.lib = lib + # XXX add 'void' handling + if self.res_type == 'int': + self.bres = BoxInt() + res = lltype.Signed + elif self.res_type == 'float': + self.bres = BoxFloat() + res = lltype.Float + elif self.res_type == 'ref': + self.bres = BoxPtr() + res = lltype.Signed + elif self.res_type == 'void': + self.bres = None + res = None + else: + raise ValueError(self.res_type) + + try: + addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func)) + except KeyError: + raise operationerrfmt(space.w_ValueError, + "Cannot find symbol %s", func) + self.bfuncaddr = BoxInt(addr) + + args = [] + for arg in self.args_type: + if arg == 'int': + args.append(lltype.Signed) + elif arg == 'float': + args.append(lltype.Float) + elif arg == 'ref': + args.append(lltype.Signed) + elif arg == 'void': + args.append(None) + else: + raise ValueError(arg) + + FPTR = lltype.Ptr(lltype.FuncType(args, res)) + FUNC = deref(FPTR) + self.calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) + + def __call__(self, *func_args): + bargs = [] + for tp, value in zip(self.args_type, func_args): + if tp == 'int': + bargs.append(BoxInt(value)) + elif tp == 'float': + bargs.append(BoxFloat(value)) + elif tp == 'ref': + bargs.append(BoxPtr(value)) + elif tp == 'void': + bargs + + bargs = [ BoxInt(x) for x in func_args ] + inputargs = [self.bfuncaddr] + bargs + + oplist = [ResOperation(rop.CALL, inputargs, self.bres, + descr=self.calldescr), + ResOperation(rop.FINISH, [self.bres], None, + descr=BasicFailDescr(0))] + looptoken = LoopToken() + self.cpu.compile_loop(inputargs, oplist, looptoken) + + i = 0 + for box in inputargs: + self.cpu.set_future_value_int(i, box.getint()) + i += 1 + + res = self.cpu.execute_token(looptoken) + if res is oplist[-1].descr: + self.guard_failed = False + else: + self.guard_failed = True + + if self.res_type == 'int': + r = BoxInt(self.cpu.get_latest_value_int(0)).getint() + elif self.res_type == 'float': + r = BoxFloat(self.cpu.get_latest_value_float(0)).getfloat() + elif self.res_type == 'ref': + r = BoxPtr(self.cpu.get_latest_value_ref(0)).getref() + elif self.res_type == 'void': + r = None + else: + raise ValueError(self.res_type) + return r Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Thu Jun 3 00:32:33 2010 @@ -58,3 +58,23 @@ #res = lib.call('return_float', [1.5, 1.2], 'float') #assert 2.7 == res + def test_get_with_same_type(self): + lib = jitffi.CDLL(self.lib_name) + + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 3 == func(1,2) + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 1 == func(-1,2) + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 0 == func(0,0) + + func = lib.get('max3', ['int', 'int', 'int'], 'int') + assert 8 == func(2, 8, 3) + + #res = lib.get('return_float', ['float', 'float'], 'float') + #assert 2.7 == func(1.5, 1.2) + + def test_get_void(self): + lib = jitffi.CDLL(self.lib_name) + py.test.raises(ValueError, lib.get, + 'add_integers', ['void', 'int'], 'int') From getxsick at codespeak.net Thu Jun 3 00:34:34 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 3 Jun 2010 00:34:34 +0200 (CEST) Subject: [pypy-svn] r75035 - pypy/branch/fast-ctypes/pypy/rlib Message-ID: <20100602223434.D6C41282BD4@codespeak.net> Author: getxsick Date: Thu Jun 3 00:34:33 2010 New Revision: 75035 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Log: kill imports Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Thu Jun 3 00:34:33 2010 @@ -1,6 +1,4 @@ from pypy.interpreter.error import operationerrfmt -from pypy.interpreter.gateway import interp2app -from pypy.interpreter.typedef import TypeDef from pypy.rlib import rdynload from pypy.rpython.lltypesystem import rffi, lltype from pypy.jit.backend.x86.runner import CPU From fijal at codespeak.net Thu Jun 3 00:54:11 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 00:54:11 +0200 (CEST) Subject: [pypy-svn] r75036 - pypy/branch/unfreeze-encodings/pypy/module/_codecs Message-ID: <20100602225411.9D15E282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 00:54:10 2010 New Revision: 75036 Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Log: Remove some nonsense. call_function will raise correct exception if asked, it's better than exploding with an rpython assertion error Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Thu Jun 3 00:54:10 2010 @@ -218,11 +218,8 @@ else: encoding = space.str_w(w_encoding) w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) - if space.is_true(w_encoder): - w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) - return space.getitem(w_res, space.wrap(0)) - else: - assert 0, "XXX, what to do here?" + w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) + return space.getitem(w_res, space.wrap(0)) encode.unwrap_spec = [ObjSpace, W_Root, W_Root, str] def buffer_encode(space, s, errors='strict'): From fijal at codespeak.net Thu Jun 3 01:05:52 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 01:05:52 +0200 (CEST) Subject: [pypy-svn] r75037 - pypy/branch/unfreeze-encodings/pypy/objspace/std Message-ID: <20100602230552.62996282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 01:05:50 2010 New Revision: 75037 Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Log: A shortcut for decoding common cases Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Thu Jun 3 01:05:50 2010 @@ -3,6 +3,7 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii from sys import maxint @@ -205,9 +206,23 @@ return w_retval def decode_object(space, w_obj, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") if encoding is None: encoding = getdefaultencoding(space) + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_ascii(s, len(s), None)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_utf_8(s, len(s), None)[0]) + except UnicodeDecodeError, ude: + raise OperationError(space.w_UnicodeDecodeError, space.newtuple( + [space.wrap(ude.encoding), space.wrap(ude.object), + space.wrap(ude.start), space.wrap(ude.end), + space.wrap(ude.reason)])) + w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: w_retval = space.call_function(w_decode, w_obj, space.wrap(encoding)) From fijal at codespeak.net Thu Jun 3 01:15:36 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 01:15:36 +0200 (CEST) Subject: [pypy-svn] r75038 - pypy/branch/unfreeze-encodings/pypy/objspace/std Message-ID: <20100602231536.E7E63282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 01:15:35 2010 New Revision: 75038 Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Log: Write down performance shortcuts for encode case Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Thu Jun 3 01:15:35 2010 @@ -3,7 +3,8 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef -from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii,\ + unicode_encode_utf_8, unicode_encode_ascii from sys import maxint @@ -184,13 +185,27 @@ return encoding, errors def encode_object(space, w_object, encoding, errors): - # XXX write down shortcuts for performance for common encodings, - # just like CPython if encoding is None: # Get the encoder functions as a wrapped object. # This lookup is cached. w_encoder = space.sys.get_w_default_encoder() else: + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_ascii(u, len(u), None)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_utf_8(u, len(u), None)) + except UnicodeEncodeError, uee: + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([ + space.wrap(uee.encoding), + space.wrap(uee.object), + space.wrap(uee.start), + space.wrap(uee.end), + space.wrap(uee.reason)])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: From fijal at codespeak.net Thu Jun 3 01:24:29 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jun 2010 01:24:29 +0200 (CEST) Subject: [pypy-svn] r75039 - pypy/branch/unfreeze-encodings/pypy/module/sys Message-ID: <20100602232429.8D07F282BD4@codespeak.net> Author: fijal Date: Thu Jun 3 01:24:28 2010 New Revision: 75039 Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Log: Obscure specialcase Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Thu Jun 3 01:24:28 2010 @@ -40,6 +40,8 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: + if loc_codeset == 'ANSI_X3.4-1968': + loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), From afa at codespeak.net Thu Jun 3 08:35:29 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 08:35:29 +0200 (CEST) Subject: [pypy-svn] r75040 - in pypy/branch/cpyext-init-cleanup/pypy/module/cpyext: . test Message-ID: <20100603063529.6B479282BD4@codespeak.net> Author: afa Date: Thu Jun 3 08:35:27 2010 New Revision: 75040 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py Log: Some progress Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Thu Jun 3 08:35:27 2010 @@ -99,6 +99,17 @@ udir.join('pypy_macros.h').write("/* Will be filled later */") globals().update(rffi_platform.configure(CConfig_constants)) +class BaseApiObject: + """Base class for all objects defined by the CPython API. each + object kind may have a declaration in a header file, a definition, + and methods to initialize it, to retrive it in test.""" + + def get_llpointer(self, space): + raise NotImplementedError + + def get_interpret(self, space): + raise NotImplementedError + def copy_header_files(): for name in ("pypy_decl.h", "pypy_macros.h"): udir.join(name).copy(interfaces_dir / name) @@ -125,7 +136,7 @@ # the error value specifed in the API. # -class ApiFunction: +class ApiFunction(BaseApiObject): def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED): self.argtypes = argtypes self.restype = restype @@ -134,9 +145,10 @@ if error is not _NOT_SPECIFIED: self.error_value = error - # extract the signature from the (CPython-level) code object + # extract the signature from user code object from pypy.interpreter import pycode - argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code) + argnames, varargname, kwargname = pycode.cpython_code_signature( + callable.func_code) assert argnames[0] == 'space' self.argnames = argnames[1:] @@ -145,15 +157,22 @@ def _freeze_(self): return True - def get_llhelper(self, space): + def get_llpointer(self, space): + "Returns a C function pointer" + assert not we_are_translated() llh = getattr(self, '_llhelper', None) if llh is None: - llh = llhelper(self.functype, self.get_wrapper(space)) + llh = llhelper(self.functype, self._get_wrapper(space)) self._llhelper = llh return llh @specialize.memo() - def get_wrapper(self, space): + def get_llpointer_maker(self, space): + "Returns a callable that builds a C function pointer" + return lambda: llhelper(self.functype, self._get_wrapper(space)) + + @specialize.memo() + def _get_wrapper(self, space): wrapper = getattr(self, '_wrapper', None) if wrapper is None: wrapper = make_wrapper(space, self.callable) @@ -377,6 +396,7 @@ cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs) PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields) PyVarObject = lltype.Ptr(PyVarObjectStruct) +PyObjectP = rffi.CArrayPtr(PyObject) @specialize.memo() def is_PyObject(TYPE): @@ -384,15 +404,6 @@ return False return hasattr(TYPE.TO, 'c_ob_refcnt') and hasattr(TYPE.TO, 'c_ob_type') -# a pointer to PyObject -PyObjectP = rffi.CArrayPtr(PyObject) - -VA_TP_LIST = {} -#{'int': lltype.Signed, -# 'PyObject*': PyObject, -# 'PyObject**': PyObjectP, -# 'int*': rffi.INTP} - def configure_types(): for name, TYPE in rffi_platform.configure(CConfig).iteritems(): if name in TYPES: @@ -522,16 +533,6 @@ wrapper.__name__ = "wrapper for %r" % (callable, ) return wrapper -def process_va_name(name): - return name.replace('*', '_star') - -def setup_va_functions(eci): - for name, TP in VA_TP_LIST.iteritems(): - name_no_star = process_va_name(name) - func = rffi.llexternal('pypy_va_get_%s' % name_no_star, [VA_LIST_P], - TP, compilation_info=eci) - globals()['va_get_%s' % name_no_star] = func - def setup_init_functions(eci): init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void, compilation_info=eci) init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void, compilation_info=eci) @@ -657,11 +658,9 @@ # implement structure initialization code for name, func in FUNCTIONS.iteritems(): pypyAPI[structindex[name]] = ctypes.cast( - ll2ctypes.lltype2ctypes(func.get_llhelper(space)), + ll2ctypes.lltype2ctypes(func.get_llpointer(space)), ctypes.c_void_p) - setup_va_functions(eci) - setup_init_functions(eci) return modulename.new(ext='') @@ -722,13 +721,6 @@ else: body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) - for name in VA_TP_LIST: - name_no_star = process_va_name(name) - header = ('%s pypy_va_get_%s(va_list* vp)' % - (name, name_no_star)) - pypy_decls.append(header + ';') - functions.append(header + '\n{return va_arg(*vp, %s);}\n' % name) - export_symbols.append('pypy_va_get_%s' % (name_no_star,)) for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): @@ -807,7 +799,6 @@ eci = build_eci(False, export_symbols, code) run_bootstrap_functions(space) - setup_va_functions(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): @@ -821,9 +812,9 @@ for name, func in FUNCTIONS.iteritems(): deco = entrypoint("cpyext", func.argtypes, name, relax=True) - deco(func.get_wrapper(space)) + deco(func._get_wrapper(space)) for name, func in FUNCTIONS_STATIC.iteritems(): - func.get_wrapper(space).c_name = name + func._get_wrapper(space).c_name = name setup_init_functions(eci) copy_header_files() Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py Thu Jun 3 08:35:27 2010 @@ -52,14 +52,10 @@ def get_dealloc(self, space): if tp_dealloc: - return llhelper( - tp_dealloc.api_func.functype, - tp_dealloc.api_func.get_wrapper(space)) + return tp_dealloc.api_func.get_llpointer_maker(space)() else: from pypy.module.cpyext.typeobject import subtype_dealloc - return llhelper( - subtype_dealloc.api_func.functype, - subtype_dealloc.api_func.get_wrapper(space)) + return subtype_dealloc.api_func.get_llpointer_maker(space)() def allocate(self, space, w_type, itemcount=0): # similar to PyType_GenericAlloc? Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py Thu Jun 3 08:35:27 2010 @@ -78,7 +78,7 @@ ml = lltype.malloc(PyMethodDef, flavor='raw', zero=True) namebuf = rffi.str2charp('func') ml.c_ml_name = namebuf - ml.c_ml_meth = c_func.get_llhelper(space) + ml.c_ml_meth = c_func.get_llpointer(space) method = PyDescr_NewMethod(space, space.w_str, ml) assert repr(method).startswith( Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py Thu Jun 3 08:35:27 2010 @@ -111,8 +111,7 @@ if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: os.write(2, method_name + " defined by the type but no slot function defined!\n") continue - slot_func_helper = llhelper(slot_func.api_func.functype, - slot_func.api_func.get_wrapper(space)) + slot_func_helper = slot_func.api_func.get_llpointer_maker(space)() # XXX special case wrapper-functions and use a "specific" slot func if len(slot_name) == 1: @@ -190,8 +189,7 @@ def setup_new_method_def(space): ptr = get_new_method_def(space) ptr.c_ml_meth = rffi.cast(PyCFunction, - llhelper(tp_new_wrapper.api_func.functype, - tp_new_wrapper.api_func.get_wrapper(space))) + tp_new_wrapper.api_func.get_llpointer_maker(space)()) def add_tp_new_wrapper(space, dict_w, pto): if "__new__" in dict_w: @@ -321,8 +319,7 @@ def subtype_dealloc(space, obj): pto = obj.c_ob_type base = pto - this_func_ptr = llhelper(subtype_dealloc.api_func.functype, - subtype_dealloc.api_func.get_wrapper(space)) + this_func_ptr = subtype_dealloc.api_func.get_llpointer_maker(space)() while base.c_tp_dealloc == this_func_ptr: base = base.c_tp_base assert base @@ -355,10 +352,9 @@ def setup_string_buffer_procs(space, pto): c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True) - c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype, - str_segcount.api_func.get_wrapper(space)) - c_buf.c_bf_getreadbuffer = llhelper(str_getreadbuffer.api_func.functype, - str_getreadbuffer.api_func.get_wrapper(space)) + c_buf.c_bf_getsegcount = str_segcount.api_func.get_llpointer_maker(space)() + c_buf.c_bf_getreadbuffer = str_getreadbuffer.api_func.get_llpointer_maker( + space)() pto.c_tp_as_buffer = c_buf @cpython_api([PyObject], lltype.Void, external=False) @@ -402,10 +398,8 @@ setup_string_buffer_procs(space, pto) pto.c_tp_flags = Py_TPFLAGS_HEAPTYPE - pto.c_tp_free = llhelper(PyObject_Del.api_func.functype, - PyObject_Del.api_func.get_wrapper(space)) - pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype, - PyType_GenericAlloc.api_func.get_wrapper(space)) + pto.c_tp_free = PyObject_Del.api_func.get_llpointer_maker(space)() + pto.c_tp_alloc = PyType_GenericAlloc.api_func.get_llpointer_maker(space)() pto.c_tp_name = rffi.str2charp(w_type.getname(space, "?")) pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out pto.c_tp_itemsize = 0 From afa at codespeak.net Thu Jun 3 10:47:07 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 10:47:07 +0200 (CEST) Subject: [pypy-svn] r75041 - in pypy/trunk/pypy/tool: . test Message-ID: <20100603084707.DF8E8282BDE@codespeak.net> Author: afa Date: Thu Jun 3 10:47:06 2010 New Revision: 75041 Added: pypy/trunk/pypy/tool/test/test_sourcetools.py (contents, props changed) Modified: pypy/trunk/pypy/tool/sourcetools.py Log: A decorator to rename a function Modified: pypy/trunk/pypy/tool/sourcetools.py ============================================================================== --- pypy/trunk/pypy/tool/sourcetools.py (original) +++ pypy/trunk/pypy/tool/sourcetools.py Thu Jun 3 10:47:06 2010 @@ -227,6 +227,12 @@ f.func_dict.update(func.func_dict) return f +def func_renamer(newname): + """A function decorator which changes the name of a function.""" + def decorate(func): + return func_with_new_name(func, newname) + return decorate + PY_IDENTIFIER = ''.join([(('0' <= chr(i) <= '9' or 'a' <= chr(i) <= 'z' or 'A' <= chr(i) <= 'Z') and chr(i) or '_') Added: pypy/trunk/pypy/tool/test/test_sourcetools.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/test/test_sourcetools.py Thu Jun 3 10:47:06 2010 @@ -0,0 +1,24 @@ +from pypy.tool.sourcetools import func_with_new_name, func_renamer + +def test_rename(): + def f(x, y=5): + return x + y + f.prop = int + + g = func_with_new_name(f, "g") + assert g(4, 5) == 9 + assert g.func_name == "g" + assert f.func_defaults == (5,) + assert g.prop is int + +def test_rename_decorator(): + @func_renamer("g") + def f(x, y=5): + return x + y + f.prop = int + + assert f(4, 5) == 9 + + assert f.func_name == "g" + assert f.func_defaults == (5,) + assert f.prop is int From arigo at codespeak.net Thu Jun 3 12:38:51 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 12:38:51 +0200 (CEST) Subject: [pypy-svn] r75042 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter metainterp Message-ID: <20100603103851.1B42536C537@codespeak.net> Author: arigo Date: Thu Jun 3 12:38:49 2010 New Revision: 75042 Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Log: Add "unreachable" as a real bytecode instead of just hoping. Remove a comment that is not completely untrue, but useless. Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py Thu Jun 3 12:38:49 2010 @@ -245,6 +245,7 @@ if block.exits[-1].exitcase == 'default': self.make_link(block.exits[-1]) else: + self.emitline("unreachable") self.emitline("---") # self.emitline('-live-') Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py Thu Jun 3 12:38:49 2010 @@ -718,6 +718,10 @@ except KeyError: return pc + @arguments() + def bhimpl_unreachable(): + raise AssertionError("unreachable") + # ---------- # exception handling operations @@ -1305,9 +1309,7 @@ def convert_and_run_from_pyjitpl(metainterp): # Get a chain of blackhole interpreters and fill them by copying - # 'metainterp.framestack'. Note that the order is important: the - # first one we get must be the bottom one, in order to make - # the comment in BlackholeInterpreter.setposition() valid. + # 'metainterp.framestack'. debug_start('jit-blackhole') metainterp_sd = metainterp.staticdata metainterp_sd.profiler.start_blackhole() Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Thu Jun 3 12:38:49 2010 @@ -324,6 +324,10 @@ except KeyError: pass + @arguments() + def opimpl_unreachable(self): + raise AssertionError("unreachable") + @arguments("descr") def opimpl_new(self, sizedescr): return self.execute_with_descr(rop.NEW, sizedescr) From arigo at codespeak.net Thu Jun 3 14:12:28 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 14:12:28 +0200 (CEST) Subject: [pypy-svn] r75043 - pypy/branch/blackhole-improvement/pypy/jit/metainterp/test Message-ID: <20100603121228.9CBBA282BDE@codespeak.net> Author: arigo Date: Thu Jun 3 14:12:26 2010 New Revision: 75043 Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py Log: Test shown rarely when running PyPy, with comment. Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py Thu Jun 3 14:12:26 2010 @@ -1,5 +1,6 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint +from pypy.rlib.jit import unroll_safe from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr @@ -395,6 +396,33 @@ self.check_aborted_count(8) self.check_enter_count_at_most(30) + def test_trace_limit_with_exception_bug(self): + myjitdriver = JitDriver(greens=[], reds=['n']) + @unroll_safe + def do_stuff(n): + while n > 0: + n -= 1 + raise ValueError + def loop(n): + pc = 0 + while n > 80: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + try: + do_stuff(n) + except ValueError: + # the trace limit is checked when we arrive here, and we + # have the exception still in last_exc_value_box at this + # point -- so when we abort because of a trace too long, + # the exception is passed to the blackhole interp and + # incorrectly re-raised from here + pass + n -= 1 + return n + TRACE_LIMIT = 66 + res = self.meta_interp(loop, [100], trace_limit=TRACE_LIMIT) + assert res == 80 + def test_max_failure_args(self): FAILARGS_LIMIT = 10 jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) From arigo at codespeak.net Thu Jun 3 14:40:36 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 14:40:36 +0200 (CEST) Subject: [pypy-svn] r75044 - in pypy/branch/blackhole-improvement/pypy/jit/metainterp: . test Message-ID: <20100603124036.A0DCF282BEC@codespeak.net> Author: arigo Date: Thu Jun 3 14:40:35 2010 New Revision: 75044 Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py Log: Fix for r75043. Add a test for the case of vable_after_residual_call(). Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py Thu Jun 3 14:40:35 2010 @@ -1307,7 +1307,7 @@ metainterp_sd.profiler.end_blackhole() debug_stop('jit-blackhole') -def convert_and_run_from_pyjitpl(metainterp): +def convert_and_run_from_pyjitpl(metainterp, raising_exception=False): # Get a chain of blackhole interpreters and fill them by copying # 'metainterp.framestack'. debug_start('jit-blackhole') @@ -1325,6 +1325,9 @@ current_exc = metainterp.last_exc_value_box.getref(rclass.OBJECTPTR) else: current_exc = lltype.nullptr(rclass.OBJECTPTR.TO) + if not raising_exception: + firstbh.exception_last_value = current_exc + current_exc = lltype.nullptr(rclass.OBJECTPTR.TO) # try: _run_forever(firstbh, current_exc) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Thu Jun 3 14:40:35 2010 @@ -1565,7 +1565,7 @@ # run it. from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl self.aborted_tracing(stb.reason) - convert_and_run_from_pyjitpl(self) + convert_and_run_from_pyjitpl(self, stb.raising_exception) assert False # ^^^ must raise def remove_consts_and_duplicates(self, boxes, endindex, duplicates): @@ -1834,7 +1834,10 @@ if vinfo.tracing_after_residual_call(virtualizable): # the virtualizable escaped during CALL_MAY_FORCE. self.load_fields_from_virtualizable() - raise SwitchToBlackhole(ABORT_ESCAPE) + raise SwitchToBlackhole(ABORT_ESCAPE, raising_exception=True) + # ^^^ we set 'raising_exception' to True because we must still + # have the eventual exception raised (this is normally done + # after the call to vable_after_residual_call()). def stop_tracking_virtualref(self, i): virtualbox = self.virtualref_boxes[i] @@ -2040,8 +2043,13 @@ it to reload the current top-of-stack frame that gets interpreted.""" class SwitchToBlackhole(JitException): - def __init__(self, reason): + def __init__(self, reason, raising_exception=False): self.reason = reason + self.raising_exception = raising_exception + # ^^^ must be set to True if the SwitchToBlackhole is raised at a + # point where the exception on metainterp.last_exc_value_box + # is supposed to be raised. The default False means that it + # should just be copied into the blackhole interp, but not raised. # ____________________________________________________________ Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py Thu Jun 3 14:40:35 2010 @@ -584,6 +584,45 @@ self.check_aborted_count(2) self.check_tree_loop_count(0) + def test_external_read_with_exception(self): + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = ['x', 'y'] + class SomewhereElse: + pass + somewhere_else = SomewhereElse() + + class FooError(Exception): + def __init__(self, value): + self.value = value + + def g(): + result = somewhere_else.top_frame.y # external read + debug_print(lltype.Void, '-+-+-+-+- external read:', result) + raise FooError(result) + + def f(n): + frame = Frame() + frame.x = n + frame.y = 10 + somewhere_else.top_frame = frame + while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) + try: + g() + except FooError, e: + frame.x -= e.value + frame.y += 1 + return frame.x + + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) + assert res == f(123) + self.check_aborted_count(2) + self.check_tree_loop_count(0) + def test_external_write(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) From arigo at codespeak.net Thu Jun 3 14:54:16 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 14:54:16 +0200 (CEST) Subject: [pypy-svn] r75045 - pypy/benchmarks Message-ID: <20100603125416.CCED6282BEC@codespeak.net> Author: arigo Date: Thu Jun 3 14:54:15 2010 New Revision: 75045 Modified: pypy/benchmarks/saveresults.py Log: Hah. In case of a server error, send() returns 1, and its return value is happily ignored anyway. Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Thu Jun 3 14:54:15 2010 @@ -14,6 +14,7 @@ #Parse data data = {} current_date = datetime.today() + error = 0 for b in results: bench_name = b[0] @@ -40,7 +41,9 @@ if res_type == "ComparisonResult": data['std_dev'] = results['std_changed'] if testing: testparams.append(data) - else: send(data) + else: error |= send(data) + if error: + raise IOError("Saving failed. See messages above.") if testing: return testparams else: return 0 From arigo at codespeak.net Thu Jun 3 14:59:23 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 14:59:23 +0200 (CEST) Subject: [pypy-svn] r75046 - pypy/benchmarks Message-ID: <20100603125923.722FC36C394@codespeak.net> Author: arigo Date: Thu Jun 3 14:59:22 2010 New Revision: 75046 Modified: pypy/benchmarks/saveresults.py Log: Always just print the exception that we got, instead of being clever and sometimes masking the real reason with other messages. Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Thu Jun 3 14:59:22 2010 @@ -64,9 +64,9 @@ response = '\n We failed to reach a server\n' response += ' Reason: ' + str(e.reason) elif hasattr(e, 'code'): - response = '\n The server couldn\'t fulfill the request\n' - response += ' Error code: ' + str(e) + response = '\n The server couldn\'t fulfill the request' print("Server (%s) response: %s\n" % (SPEEDURL, response)) + print(' Error code: ' + str(e)) return 1 print "saved correctly!\n" return 0 From arigo at codespeak.net Thu Jun 3 15:37:48 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 15:37:48 +0200 (CEST) Subject: [pypy-svn] r75047 - pypy/trunk/pypy/translator/c/test Message-ID: <20100603133748.71470282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 15:37:46 2010 New Revision: 75047 Modified: pypy/trunk/pypy/translator/c/test/test_standalone.py Log: Add an assert that fails when we run this with pypy instead of cpython. Modified: pypy/trunk/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_standalone.py (original) +++ pypy/trunk/pypy/translator/c/test/test_standalone.py Thu Jun 3 15:37:46 2010 @@ -210,6 +210,7 @@ filename = str(udir.join('test_standalone_largefile')) r4800000000 = r_longlong(4800000000L) def entry_point(argv): + assert str(r4800000000 + len(argv)) == '4800000001' fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644) os.lseek(fd, r4800000000, 0) newpos = os.lseek(fd, 0, 1) From arigo at codespeak.net Thu Jun 3 15:39:05 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 15:39:05 +0200 (CEST) Subject: [pypy-svn] r75048 - pypy/trunk/pypy/translator/c/test Message-ID: <20100603133905.84F9B282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 15:39:04 2010 New Revision: 75048 Modified: pypy/trunk/pypy/translator/c/test/test_standalone.py Log: Ah. Sorry. Modified: pypy/trunk/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_standalone.py (original) +++ pypy/trunk/pypy/translator/c/test/test_standalone.py Thu Jun 3 15:39:04 2010 @@ -210,7 +210,7 @@ filename = str(udir.join('test_standalone_largefile')) r4800000000 = r_longlong(4800000000L) def entry_point(argv): - assert str(r4800000000 + len(argv)) == '4800000001' + assert str(r4800000000 + len(argv)) == '4800000003' fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644) os.lseek(fd, r4800000000, 0) newpos = os.lseek(fd, 0, 1) From arigo at codespeak.net Thu Jun 3 15:43:48 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 15:43:48 +0200 (CEST) Subject: [pypy-svn] r75049 - pypy/trunk/pypy/objspace/std/test Message-ID: <20100603134348.374DE282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 15:43:46 2010 New Revision: 75049 Modified: pypy/trunk/pypy/objspace/std/test/test_stringformat.py Log: Add passing tests. Modified: pypy/trunk/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_stringformat.py Thu Jun 3 15:43:46 2010 @@ -125,6 +125,15 @@ assert '27' == '%.2o' % n assert '027' == '%#.2o' % n + def test_format_long(self): + l = 4800000000L + assert '%d' % l == '4800000000' + # + class SubLong(long): + pass + sl = SubLong(l) + assert '%d' % sl == '4800000000' + def test_format_list(self): l = [1,2] assert '<[1, 2]>' == '<%s>' % l From afa at codespeak.net Thu Jun 3 15:45:51 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 15:45:51 +0200 (CEST) Subject: [pypy-svn] r75050 - pypy/trunk/pypy/module/cpyext Message-ID: <20100603134551.8B2D036C230@codespeak.net> Author: afa Date: Thu Jun 3 15:45:50 2010 New Revision: 75050 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: This may cause compilation warnings (PyExc_ValueError is supposed to be a PyObject*) but at least the translator will generate a full PyTypeObject static structure, and avoid crashes. Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Thu Jun 3 15:45:50 2010 @@ -315,7 +315,7 @@ # Standard exceptions for exc_name in exceptions.Module.interpleveldefs.keys(): GLOBALS['PyExc_' + exc_name] = ( - 'PyObject*', + 'PyTypeObject*', 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, )) # Common types with their own struct From arigo at codespeak.net Thu Jun 3 15:53:17 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 15:53:17 +0200 (CEST) Subject: [pypy-svn] r75051 - pypy/branch/int_is_not_intmask Message-ID: <20100603135317.C135B36C231@codespeak.net> Author: arigo Date: Thu Jun 3 15:53:16 2010 New Revision: 75051 Added: pypy/branch/int_is_not_intmask/ (props changed) - copied from r75050, pypy/trunk/ Log: A branch in which to remove __int__ from class base_int in rlib.rarithmetic. From arigo at codespeak.net Thu Jun 3 15:55:40 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 15:55:40 +0200 (CEST) Subject: [pypy-svn] r75052 - in pypy/branch/int_is_not_intmask/pypy/rlib: . test Message-ID: <20100603135540.46BA836C231@codespeak.net> Author: arigo Date: Thu Jun 3 15:55:38 2010 New Revision: 75052 Modified: pypy/branch/int_is_not_intmask/pypy/rlib/rarithmetic.py pypy/branch/int_is_not_intmask/pypy/rlib/test/test_rarithmetic.py Log: Remove __int__, and disable the test. Modified: pypy/branch/int_is_not_intmask/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/int_is_not_intmask/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/int_is_not_intmask/pypy/rlib/rarithmetic.py Thu Jun 3 15:55:38 2010 @@ -178,12 +178,6 @@ else: return super(base_int, klass).__new__(klass, val) - def __int__(self): - if self < LONG_TEST: - return long.__int__(self) - else: - return intmask(self) - def __add__(self, other): x = long(self) y = long(other) Modified: pypy/branch/int_is_not_intmask/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/branch/int_is_not_intmask/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/branch/int_is_not_intmask/pypy/rlib/test/test_rarithmetic.py Thu Jun 3 15:55:38 2010 @@ -114,7 +114,10 @@ #self.binary_test(lambda x, y: pow(x, y, 42), (2, 3, 5, 1000)) def test_back_to_int(self): - assert int(r_uint(-1)) == -1 + #assert int(r_uint(-1)) == -1 + # ^^^ that looks wrong IMHO: int(x) should not by itself return + # an integer that has a different value than x, especially + # if x is a subclass of long. assert int(r_uint(1)) == 1 def unary_test(self, f): From jcreigh at codespeak.net Thu Jun 3 16:48:49 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Thu, 3 Jun 2010 16:48:49 +0200 (CEST) Subject: [pypy-svn] r75053 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100603144849.8A9D8282BD6@codespeak.net> Author: jcreigh Date: Thu Jun 3 16:48:47 2010 New Revision: 75053 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Log: make AssemblerLocation inherit from object instead of AbstractValue Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Thu Jun 3 16:48:47 2010 @@ -9,7 +9,7 @@ # mc.ADD_rr()/ADD_rb()/ADD_ri(). # -class AssemblerLocation(AbstractValue): +class AssemblerLocation(object): # XXX: Is adding "width" here correct? __slots__ = ('value', 'width') _immutable_ = True From arigo at codespeak.net Thu Jun 3 17:07:57 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 17:07:57 +0200 (CEST) Subject: [pypy-svn] r75054 - pypy/benchmarks/own/twisted Message-ID: <20100603150757.ABA92282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 17:07:55 2010 New Revision: 75054 Modified: pypy/benchmarks/own/twisted/accepts.py pypy/benchmarks/own/twisted/benchlib.py pypy/benchmarks/own/twisted/pb.py pypy/benchmarks/own/twisted/tcp.py pypy/benchmarks/own/twisted/web.py Log: Following exarkun's suggestion, avoid running out of local ports by using 127.0.0.2, 127.0.0.3, etc. Modified: pypy/benchmarks/own/twisted/accepts.py ============================================================================== --- pypy/benchmarks/own/twisted/accepts.py (original) +++ pypy/benchmarks/own/twisted/accepts.py Thu Jun 3 17:07:55 2010 @@ -5,12 +5,13 @@ from twisted.internet.error import ConnectionClosed from twisted.internet.defer import Deferred -from benchlib import Client, driver +from benchlib import Client, driver, rotate_local_intf class Client(Client): - def __init__(self, reactor, portNumber): + def __init__(self, reactor, host, portNumber): super(Client, self).__init__(reactor) + self._host = host self._portNumber = portNumber self._factory = ClientFactory() @@ -21,7 +22,7 @@ factory.protocol = Protocol factory.clientConnectionLost = factory.clientConnectionFailed = lambda connector, reason: finished.errback(reason) finished.addErrback(self._filterFinished) - self._reactor.connectTCP('127.0.0.1', self._portNumber, factory) + self._reactor.connectTCP(self._host, self._portNumber, factory) finished.addCallback(self._continue) finished.addErrback(self._stop) @@ -41,9 +42,10 @@ factory = ServerFactory() factory.protocol = CloseConnection - port = reactor.listenTCP(0, factory) + port = reactor.listenTCP(0, factory, + interface=rotate_local_intf()) - client = Client(reactor, port.getHost().port) + client = Client(reactor, port.getHost().host, port.getHost().port) d = client.run(concurrency, duration) return d Modified: pypy/benchmarks/own/twisted/benchlib.py ============================================================================== --- pypy/benchmarks/own/twisted/benchlib.py (original) +++ pypy/benchmarks/own/twisted/benchlib.py Thu Jun 3 17:07:55 2010 @@ -92,3 +92,9 @@ reactor.stop() reactor.callWhenRunning(work) reactor.run() + +_interface = 1 +def rotate_local_intf(): + global _interface + _interface = _interface % 254 + 1 + return '127.0.0.%d' % (_interface,) Modified: pypy/benchmarks/own/twisted/pb.py ============================================================================== --- pypy/benchmarks/own/twisted/pb.py (original) +++ pypy/benchmarks/own/twisted/pb.py Thu Jun 3 17:07:55 2010 @@ -7,7 +7,7 @@ from twisted.spread.pb import PBServerFactory, PBClientFactory, Root -from benchlib import Client, driver +from benchlib import Client, driver, rotate_local_intf class BenchRoot(Root): @@ -23,8 +23,9 @@ 'baz': 100, u'these are bytes': (1, 2, 3)}] - def __init__(self, reactor, port): + def __init__(self, reactor, host, port): super(Client, self).__init__(reactor) + self._host = host self._port = port @@ -35,7 +36,7 @@ client = PBClientFactory() d = client.getRootObject() d.addCallback(connected) - self._reactor.connectTCP('127.0.0.1', self._port, client) + self._reactor.connectTCP(self._host, self._port, client) return d @@ -49,8 +50,9 @@ concurrency = 15 server = PBServerFactory(BenchRoot()) - port = reactor.listenTCP(0, server) - client = Client(reactor, port.getHost().port) + port = reactor.listenTCP(0, server, + interface=rotate_local_intf()) + client = Client(reactor, port.getHost().host, port.getHost().port) d = client.run(concurrency, duration) return d Modified: pypy/benchmarks/own/twisted/tcp.py ============================================================================== --- pypy/benchmarks/own/twisted/tcp.py (original) +++ pypy/benchmarks/own/twisted/tcp.py Thu Jun 3 17:07:55 2010 @@ -13,7 +13,7 @@ from twisted.internet.protocol import ServerFactory, ClientCreator, Protocol from twisted.protocols.wire import Echo -from benchlib import driver +from benchlib import driver, rotate_local_intf class Counter(Protocol): @@ -27,8 +27,9 @@ class Client(object): _finished = None - def __init__(self, reactor, port): + def __init__(self, reactor, host, port): self._reactor = reactor + self._host = host self._port = port @@ -37,7 +38,7 @@ self._bytes = 'x' * chunkSize # Set up a connection cc = ClientCreator(self._reactor, Counter) - d = cc.connectTCP('127.0.0.1', self._port) + d = cc.connectTCP(self._host, self._port) d.addCallback(self._connected) return d @@ -81,8 +82,10 @@ server = ServerFactory() server.protocol = Echo - serverPort = reactor.listenTCP(0, server) - client = Client(reactor, serverPort.getHost().port) + serverPort = reactor.listenTCP(0, server, + interface=rotate_local_intf()) + client = Client(reactor, serverPort.getHost().host, + serverPort.getHost().port) d = client.run(duration, chunkSize) return d Modified: pypy/benchmarks/own/twisted/web.py ============================================================================== --- pypy/benchmarks/own/twisted/web.py (original) +++ pypy/benchmarks/own/twisted/web.py Thu Jun 3 17:07:55 2010 @@ -20,7 +20,7 @@ from twisted.web.resource import Resource from twisted.web.client import ResponseDone, Agent -from benchlib import Client, driver +from benchlib import Client, driver, rotate_local_intf class BodyConsumer(Protocol): @@ -36,8 +36,8 @@ class Client(Client): - def __init__(self, reactor, portNumber, agent): - self._requestLocation = 'http://127.0.0.1:%d/' % (portNumber,) + def __init__(self, reactor, host, portNumber, agent): + self._requestLocation = 'http://%s:%d/' % (host, portNumber) self._agent = agent super(Client, self).__init__(reactor) @@ -62,9 +62,9 @@ root = Resource() root.putChild('', Data("Hello, world", "text/plain")) port = reactor.listenTCP( - 0, Site(root), backlog=128, interface='127.0.0.1') + 0, Site(root), backlog=128, interface=rotate_local_intf()) agent = Agent(reactor) - client = Client(reactor, port.getHost().port, agent) + client = Client(reactor, port.getHost().host, port.getHost().port, agent) d = client.run(concurrency, duration) return d From getxsick at codespeak.net Thu Jun 3 18:05:56 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 3 Jun 2010 18:05:56 +0200 (CEST) Subject: [pypy-svn] r75055 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100603160556.8DE1436C374@codespeak.net> Author: getxsick Date: Thu Jun 3 18:05:55 2010 New Revision: 75055 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: support other types than integers. it still needs some work... Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Thu Jun 3 18:05:55 2010 @@ -138,9 +138,7 @@ elif tp == 'ref': bargs.append(BoxPtr(value)) elif tp == 'void': - bargs - - bargs = [ BoxInt(x) for x in func_args ] + assert False #XXX inputargs = [self.bfuncaddr] + bargs oplist = [ResOperation(rop.CALL, inputargs, self.bres, @@ -150,10 +148,15 @@ looptoken = LoopToken() self.cpu.compile_loop(inputargs, oplist, looptoken) - i = 0 - for box in inputargs: - self.cpu.set_future_value_int(i, box.getint()) - i += 1 + for i, box in enumerate(inputargs): + if i == 0: # func address + self.cpu.set_future_value_int(i, box.getint()) + elif self.args_type[i-1] == 'int': + self.cpu.set_future_value_int(i, box.getint()) + elif self.args_type[i-1] == 'float': + self.cpu.set_future_value_float(i, box.getfloat()) + elif self.args_type[i-1] == 'ref': + self.cpu.set_future_value_ref(i, box.getref()) res = self.cpu.execute_token(looptoken) if res is oplist[-1].descr: Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Thu Jun 3 18:05:55 2010 @@ -15,7 +15,12 @@ return a+b; } - float return_float(int a, int b) + double add_floats(double a, double b) + { + return a+b; + } + + double return_float(int a, int b) { return a+b; } @@ -30,7 +35,7 @@ ''' )) - symbols = ["add_integers"] + symbols = ['add_integers', 'add_floats', 'return_float', 'max3'] eci = ExternalCompilationInfo(export_symbols=symbols) return str(platform.compile([c_file], eci, 'x', standalone=False)) @@ -71,8 +76,8 @@ func = lib.get('max3', ['int', 'int', 'int'], 'int') assert 8 == func(2, 8, 3) - #res = lib.get('return_float', ['float', 'float'], 'float') - #assert 2.7 == func(1.5, 1.2) + func = lib.get('add_floats', ['float', 'float'], 'float') + assert 2.7 == func(1.2, 1.5) def test_get_void(self): lib = jitffi.CDLL(self.lib_name) From arigo at codespeak.net Thu Jun 3 18:39:09 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 18:39:09 +0200 (CEST) Subject: [pypy-svn] r75057 - pypy/benchmarks Message-ID: <20100603163909.12F31282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 18:39:08 2010 New Revision: 75057 Modified: pypy/benchmarks/saveresults.py Log: Fix \n-ing. Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Thu Jun 3 18:39:08 2010 @@ -65,8 +65,8 @@ response += ' Reason: ' + str(e.reason) elif hasattr(e, 'code'): response = '\n The server couldn\'t fulfill the request' - print("Server (%s) response: %s\n" % (SPEEDURL, response)) - print(' Error code: ' + str(e)) + print("Server (%s) response: %s" % (SPEEDURL, response)) + print(' Error code: %s\n' % (e,)) return 1 print "saved correctly!\n" return 0 From jcreigh at codespeak.net Thu Jun 3 19:07:58 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Thu, 3 Jun 2010 19:07:58 +0200 (CEST) Subject: [pypy-svn] r75059 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend: llsupport x86 x86/test Message-ID: <20100603170758.8A310282BD6@codespeak.net> Author: jcreigh Date: Thu Jun 3 19:07:56 2010 New Revision: 75059 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_jump.py Log: store the type (INT, REF, or FLOAT) of a StackLoc so we can tell the difference between a 64-bit int and a 64-bit float Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/regalloc.py Thu Jun 3 19:07:56 2010 @@ -22,18 +22,19 @@ def get(self, box): return self.frame_bindings.get(box, None) - def loc(self, box, size): + def loc(self, box): res = self.get(box) if res is not None: return res - newloc = self.frame_pos(self.frame_depth, size) + newloc = self.frame_pos(self.frame_depth, box.type) self.frame_bindings[box] = newloc - self.frame_depth += size + # Objects returned by frame_pos must support frame_size() + self.frame_depth += newloc.frame_size() return newloc # abstract methods that need to be overwritten for specific assemblers @staticmethod - def frame_pos(loc, size): + def frame_pos(loc, type): raise NotImplementedError("Purely abstract") class RegisterManager(object): @@ -43,7 +44,6 @@ all_regs = [] no_lower_byte_regs = [] save_around_call_regs = [] - reg_width = 1 # in terms of stack space eaten def __init__(self, longevity, frame_manager=None, assembler=None): self.free_regs = self.all_regs[:] @@ -148,7 +148,7 @@ loc = self.reg_bindings[v_to_spill] del self.reg_bindings[v_to_spill] if self.frame_manager.get(v_to_spill) is None: - newloc = self.frame_manager.loc(v_to_spill, self.reg_width) + newloc = self.frame_manager.loc(v_to_spill) self.assembler.regalloc_mov(loc, newloc) return loc @@ -204,7 +204,7 @@ try: return self.reg_bindings[box] except KeyError: - return self.frame_manager.loc(box, self.reg_width) + return self.frame_manager.loc(box) def return_constant(self, v, forbidden_vars=[], selected_reg=None, imm_fine=True): @@ -260,7 +260,7 @@ self.reg_bindings[v] = loc self.assembler.regalloc_mov(prev_loc, loc) else: - loc = self.frame_manager.loc(v, self.reg_width) + loc = self.frame_manager.loc(v) self.assembler.regalloc_mov(prev_loc, loc) def force_result_in_reg(self, result_v, v, forbidden_vars=[]): @@ -280,7 +280,7 @@ self.free_regs = [reg for reg in self.free_regs if reg is not loc] return loc if v not in self.reg_bindings: - prev_loc = self.frame_manager.loc(v, self.reg_width) + prev_loc = self.frame_manager.loc(v) loc = self.force_allocate_reg(v, forbidden_vars) self.assembler.regalloc_mov(prev_loc, loc) assert v in self.reg_bindings @@ -300,7 +300,7 @@ def _sync_var(self, v): if not self.frame_manager.get(v): reg = self.reg_bindings[v] - to = self.frame_manager.loc(v, self.reg_width) + to = self.frame_manager.loc(v) self.assembler.regalloc_mov(reg, to) # otherwise it's clean Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Thu Jun 3 19:07:56 2010 @@ -1118,6 +1118,7 @@ def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager + descr_to_box_type = [REF, INT, FLOAT] bytecode = rffi.cast(rffi.UCHARP, bytecode) arglocs = [] while 1: @@ -1142,7 +1143,7 @@ size = 2 else: size = 1 - loc = X86FrameManager.frame_pos(code, size) + loc = X86FrameManager.frame_pos(code, descr_to_box_type[kind]) elif code == self.CODE_STOP: break elif code == self.CODE_HOLE: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Thu Jun 3 19:07:56 2010 @@ -81,7 +81,6 @@ all_regs = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7] # we never need lower byte I hope save_around_call_regs = all_regs - reg_width = 2 def __init__(self, longevity, frame_manager=None, assembler=None): RegisterManager.__init__(self, longevity, frame_manager=frame_manager, @@ -101,16 +100,17 @@ # the result is stored in st0, but we don't have this around, # so genop_call will move it to some frame location immediately # after the call - return self.frame_manager.loc(v, 2) + return self.frame_manager.loc(v) class X86FrameManager(FrameManager): @staticmethod - def frame_pos(i, size): + def frame_pos(i, box_type): + size = width_of_type[box_type] if size == 1: - return StackLoc(i, get_ebp_ofs(i), size) + return StackLoc(i, get_ebp_ofs(i), size, box_type) elif size == 2: - return StackLoc(i, get_ebp_ofs(i+1), size) + return StackLoc(i, get_ebp_ofs(i+1), size, box_type) else: print "Unimplemented size %d" % i raise NotImplementedError("unimplemented size %d" % i) @@ -183,7 +183,7 @@ if reg: loc = reg else: - loc = self.fm.loc(arg, width_of_type[arg.type]) + loc = self.fm.loc(arg) if arg.type == FLOAT: floatlocs[i] = loc else: @@ -656,7 +656,7 @@ vable_index = self.assembler.cpu.index_of_virtualizable if vable_index != -1: self.rm._sync_var(op.args[vable_index]) - vable = self.fm.loc(op.args[vable_index], 1) + vable = self.fm.loc(op.args[vable_index]) else: vable = imm(0) self._call(op, [imm(size), vable] + Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Thu Jun 3 19:07:56 2010 @@ -25,12 +25,19 @@ class StackLoc(AssemblerLocation): _immutable_ = True - def __init__(self, position, ebp_offset, num_words): + def __init__(self, position, ebp_offset, num_words, type): assert ebp_offset < 0 # so no confusion with RegLoc.value self.position = position self.value = ebp_offset # XXX: Word size hardcoded self.width = num_words * 4 + # One of INT, REF, FLOAT + self.type = type + + def frame_size(self): + # XXX: word size + return self.width // 4 + def __repr__(self): return '%d(%%ebp)' % (self.value,) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Thu Jun 3 19:07:56 2010 @@ -1,7 +1,7 @@ from pypy.jit.backend.x86.regloc import * from pypy.jit.backend.x86.assembler import Assembler386, MachineCodeBlockWrapper from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs -from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT from pypy.rlib.rarithmetic import intmask from pypy.rpython.lltypesystem import lltype, llmemory, rffi @@ -33,12 +33,12 @@ failargs = [BoxInt(), BoxPtr(), BoxFloat()] * 3 failargs.insert(6, None) failargs.insert(7, None) - locs = [X86FrameManager.frame_pos(0, 1), - X86FrameManager.frame_pos(1, 1), - X86FrameManager.frame_pos(10, 2), - X86FrameManager.frame_pos(100, 1), - X86FrameManager.frame_pos(101, 1), - X86FrameManager.frame_pos(110, 2), + locs = [X86FrameManager.frame_pos(0, INT), + X86FrameManager.frame_pos(1, REF), + X86FrameManager.frame_pos(10, FLOAT), + X86FrameManager.frame_pos(100, INT), + X86FrameManager.frame_pos(101, REF), + X86FrameManager.frame_pos(110, FLOAT), None, None, ebx, Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py Thu Jun 3 19:07:56 2010 @@ -1,5 +1,5 @@ import py -from pypy.jit.backend.x86.runner import CPU386 +from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.test import test_basic from pypy.jit.metainterp.policy import StopAtXPolicy @@ -7,7 +7,7 @@ class Jit386Mixin(test_basic.LLJitMixin): type_system = 'lltype' - CPUClass = CPU386 + CPUClass = getcpuclass() def check_jumps(self, maxcount): pass Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_jump.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_jump.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_jump.py Thu Jun 3 19:07:56 2010 @@ -1,6 +1,7 @@ from pypy.jit.backend.x86.regloc import * from pypy.jit.backend.x86.regalloc import X86FrameManager from pypy.jit.backend.x86.jump import remap_frame_layout +from pypy.jit.metainterp.history import INT frame_pos = X86FrameManager.frame_pos @@ -41,9 +42,9 @@ remap_frame_layout(assembler, [eax, ebx, ecx, edx, esi, edi], [eax, ebx, ecx, edx, esi, edi], '?') assert assembler.ops == [] - s8 = frame_pos(1, 1) - s12 = frame_pos(31, 1) - s20 = frame_pos(6, 1) + s8 = frame_pos(1, INT) + s12 = frame_pos(31, INT) + s20 = frame_pos(6, INT) remap_frame_layout(assembler, [eax, ebx, ecx, s20, s8, edx, s12, esi, edi], [eax, ebx, ecx, s20, s8, edx, s12, esi, edi], '?') @@ -58,10 +59,10 @@ def test_simple_framelocs(): assembler = MockAssembler() - s8 = frame_pos(0, 1) - s12 = frame_pos(13, 1) - s20 = frame_pos(20, 1) - s24 = frame_pos(221, 1) + s8 = frame_pos(0, INT) + s12 = frame_pos(13, INT) + s20 = frame_pos(20, INT) + s24 = frame_pos(221, INT) remap_frame_layout(assembler, [s8, eax, s12], [s20, s24, edi], edx) assert assembler.ops == [('mov', s8, edx), ('mov', edx, s20), @@ -70,10 +71,10 @@ def test_reordering(): assembler = MockAssembler() - s8 = frame_pos(8, 1) - s12 = frame_pos(12, 1) - s20 = frame_pos(19, 1) - s24 = frame_pos(1, 1) + s8 = frame_pos(8, INT) + s12 = frame_pos(12, INT) + s20 = frame_pos(19, INT) + s24 = frame_pos(1, INT) remap_frame_layout(assembler, [eax, s8, s20, ebx], [s8, ebx, eax, edi], '?') assert assembler.got([('mov', ebx, edi), @@ -83,10 +84,10 @@ def test_cycle(): assembler = MockAssembler() - s8 = frame_pos(8, 1) - s12 = frame_pos(12, 1) - s20 = frame_pos(19, 1) - s24 = frame_pos(1, 1) + s8 = frame_pos(8, INT) + s12 = frame_pos(12, INT) + s20 = frame_pos(19, INT) + s24 = frame_pos(1, INT) remap_frame_layout(assembler, [eax, s8, s20, ebx], [s8, ebx, eax, s20], '?') assert assembler.got([('push', s8), @@ -97,12 +98,12 @@ def test_cycle_2(): assembler = MockAssembler() - s8 = frame_pos(8, 1) - s12 = frame_pos(12, 1) - s20 = frame_pos(19, 1) - s24 = frame_pos(1, 1) - s2 = frame_pos(2, 1) - s3 = frame_pos(3, 1) + s8 = frame_pos(8, INT) + s12 = frame_pos(12, INT) + s20 = frame_pos(19, INT) + s24 = frame_pos(1, INT) + s2 = frame_pos(2, INT) + s3 = frame_pos(3, INT) remap_frame_layout(assembler, [eax, s8, edi, s20, eax, s20, s24, esi, s2, s3], [s8, s20, edi, eax, edx, s24, ebx, s12, s3, s2], @@ -127,14 +128,14 @@ remap_frame_layout(assembler, [c3], [eax], '?') assert assembler.ops == [('mov', c3, eax)] assembler = MockAssembler() - s12 = frame_pos(12, 1) + s12 = frame_pos(12, INT) remap_frame_layout(assembler, [c3], [s12], '?') assert assembler.ops == [('mov', c3, s12)] def test_constants_and_cycle(): assembler = MockAssembler() c3 = imm(3) - s12 = frame_pos(13, 1) + s12 = frame_pos(13, INT) remap_frame_layout(assembler, [ebx, c3, s12], [s12, eax, ebx], edi) assert assembler.ops == [('mov', c3, eax), From benjamin at codespeak.net Thu Jun 3 19:08:11 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 19:08:11 +0200 (CEST) Subject: [pypy-svn] r75060 - pypy/branch/fast-forward Message-ID: <20100603170811.13393282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 19:08:10 2010 New Revision: 75060 Added: pypy/branch/fast-forward/ (props changed) - copied from r75058, pypy/trunk/ Log: branch to upgrade python versions From benjamin at codespeak.net Thu Jun 3 19:35:48 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 19:35:48 +0200 (CEST) Subject: [pypy-svn] r75061 - pypy/branch/fast-forward/lib-python Message-ID: <20100603173548.B052D282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 19:35:47 2010 New Revision: 75061 Modified: pypy/branch/fast-forward/lib-python/ (props changed) Log: include 2.7's stdlib From getxsick at codespeak.net Thu Jun 3 19:36:27 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 3 Jun 2010 19:36:27 +0200 (CEST) Subject: [pypy-svn] r75062 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100603173627.908CC282BD6@codespeak.net> Author: getxsick Date: Thu Jun 3 19:36:26 2010 New Revision: 75062 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: kill space Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Thu Jun 3 19:36:26 2010 @@ -1,4 +1,3 @@ -from pypy.interpreter.error import operationerrfmt from pypy.rlib import rdynload from pypy.rpython.lltypesystem import rffi, lltype from pypy.jit.backend.x86.runner import CPU @@ -11,9 +10,9 @@ def __init__(self, name): try: self.lib = rdynload.dlopen(name) - except libffi.DLOpenError, e: - raise operationerrfmt(space.w_OSError, '%s: %s', name, - e.msg or 'unspecified error') + except rdynload.DLOpenError, e: + raise OSError('%s: %s', name, e.msg or 'unspecified error') + self.name = name self.cpu = CPU(None, None) @@ -35,8 +34,7 @@ try: addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func)) except KeyError: - raise operationerrfmt(space.w_ValueError, - "Cannot find symbol %s", func) + raise ValueError("Cannot find symbol %s", func) bfuncaddr = BoxInt(addr) args_type = [ lltype.Signed for i in func_args ] @@ -107,8 +105,7 @@ try: addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func)) except KeyError: - raise operationerrfmt(space.w_ValueError, - "Cannot find symbol %s", func) + raise ValueError("Cannot find symbol %s", func) self.bfuncaddr = BoxInt(addr) args = [] Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Thu Jun 3 19:36:26 2010 @@ -43,6 +43,9 @@ def setup_class(cls): cls.lib_name = cls.preprare_c_example() + def test_missing_lib(self): + py.test.raises(OSError, jitffi.CDLL, 'xxxfoo888baryyy') + def test_call(self): lib = jitffi.CDLL(self.lib_name) @@ -83,3 +86,9 @@ lib = jitffi.CDLL(self.lib_name) py.test.raises(ValueError, lib.get, 'add_integers', ['void', 'int'], 'int') + + def test_undefined_func(self): + lib = jitffi.CDLL(self.lib_name) + # xxxfoo888baryyy - not existed function + py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', []) + py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') From benjamin at codespeak.net Thu Jun 3 19:36:52 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 19:36:52 +0200 (CEST) Subject: [pypy-svn] r75063 - pypy/branch/fast-forward/pypy/module/sys Message-ID: <20100603173652.22F2B282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 19:36:50 2010 New Revision: 75063 Modified: pypy/branch/fast-forward/pypy/module/sys/version.py Log: change version to 2.7 Modified: pypy/branch/fast-forward/pypy/module/sys/version.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/version.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/version.py Thu Jun 3 19:36:50 2010 @@ -4,7 +4,7 @@ import os -CPYTHON_VERSION = (2, 5, 2, "beta", 42) +CPYTHON_VERSION = (2, 7, 0, "beta", 42) CPYTHON_API_VERSION = 1012 PYPY_VERSION = (1, 2, 0, "beta", '?') From benjamin at codespeak.net Thu Jun 3 19:40:59 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 19:40:59 +0200 (CEST) Subject: [pypy-svn] r75064 - pypy/branch/fast-forward/lib-python Message-ID: <20100603174059.9B370282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 19:40:58 2010 New Revision: 75064 Modified: pypy/branch/fast-forward/lib-python/ (props changed) Log: add bugfix version From arigo at codespeak.net Thu Jun 3 19:42:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 19:42:52 +0200 (CEST) Subject: [pypy-svn] r75065 - pypy/branch/unfreeze-encodings/pypy/module/sys Message-ID: <20100603174252.A941E282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 19:42:51 2010 New Revision: 75065 Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/__init__.py Log: Remove one translation-time caller of lookup_codec(). Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/sys/__init__.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/sys/__init__.py Thu Jun 3 19:42:51 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.interpreter.error import OperationError +from pypy.rlib.objectmodel import we_are_translated import sys class Module(MixedModule): @@ -92,8 +93,12 @@ self.space.setitem(w_modules, w_name, w_module) def startup(self, space): - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) + if space.config.translating and not we_are_translated(): + # don't get the filesystemencoding at translation time + assert self.filesystemencoding is None + else: + from pypy.module.sys.interp_encoding import _getfilesystemencoding + self.filesystemencoding = _getfilesystemencoding(space) def getmodule(self, name): space = self.space From arigo at codespeak.net Thu Jun 3 19:45:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 19:45:50 +0200 (CEST) Subject: [pypy-svn] r75066 - pypy/branch/unfreeze-encodings/pypy/module/_codecs Message-ID: <20100603174550.13E8E282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 19:45:49 2010 New Revision: 75066 Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Log: Assert that we don't call lookup_codec() at all during translation. Modified: pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/_codecs/interp_codecs.py Thu Jun 3 19:45:49 2010 @@ -2,6 +2,7 @@ from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder +from pypy.rlib.objectmodel import we_are_translated class CodecState(object): def __init__(self, space): @@ -78,6 +79,8 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ + assert not (space.config.translating and not we_are_translated()), \ + "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() w_result = state.codec_search_cache.get(normalized_encoding, None) From afa at codespeak.net Thu Jun 3 19:47:41 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 19:47:41 +0200 (CEST) Subject: [pypy-svn] r75067 - in pypy/trunk/pypy/module/cpyext: include patches Message-ID: <20100603174741.8E209282BD6@codespeak.net> Author: afa Date: Thu Jun 3 19:47:40 2010 New Revision: 75067 Modified: pypy/trunk/pypy/module/cpyext/include/Python.h pypy/trunk/pypy/module/cpyext/patches/boost.patch Log: Update patch for Boost.Python, one less hack if we define the (deprecated!) DL_IMPORT macro Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Thu Jun 3 19:47:40 2010 @@ -27,6 +27,7 @@ # endif # define Py_LOCAL_INLINE(type) static __inline type __fastcall #endif +#define DL_IMPORT(RTYPE) PyAPI_FUNC(RTYPE) #include Modified: pypy/trunk/pypy/module/cpyext/patches/boost.patch ============================================================================== --- pypy/trunk/pypy/module/cpyext/patches/boost.patch (original) +++ pypy/trunk/pypy/module/cpyext/patches/boost.patch Thu Jun 3 19:47:40 2010 @@ -1,16 +1,3 @@ -Index: libs/python/src/object/class.cpp -=================================================================== ---- libs/python/src/object/class.cpp 2009-11-13 01:40:01 +0100 -+++ libs/python/src/object/class.cpp 2010-06-02 23:25:08 +0200 -@@ -195,7 +195,7 @@ - - namespace objects - { --#if PY_VERSION_HEX < 0x03000000 -+#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) - // XXX Not sure why this run into compiling error in Python 3 - extern "C" - { Index: libs/python/src/object/function.cpp =================================================================== --- libs/python/src/object/function.cpp 2010-04-04 07:19:57 +0200 @@ -50,14 +37,21 @@ =================================================================== --- tools/build/v2/user-config.jam 2008-07-15 15:53:41 +0200 +++ tools/build/v2/user-config.jam 2010-06-02 23:46:13 +0200 -@@ -84,3 +84,9 @@ +@@ -84,3 +84,16 @@ # Configure with an explicit installation prefix. # using qt : /usr/opt/qt ; + ++# ------------------- ++# PyPy configuration. ++# ------------------- ++ ++PYPY_HOME = /home/amaury/trunk ; ++ +using python : 2.5 -+ : /home/amaury/trunk/pypy/pypy-c -+ : /home/amaury/trunk/pypy/module/cpyext/include -+ /home/amaury/trunk/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/pypy-c # interpreter ++ : $(PYPY_HOME)/pypy/module/cpyext/include # include paths ++ $(PYPY_HOME)/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/_interfaces # library path + ; From arigo at codespeak.net Thu Jun 3 19:51:56 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 19:51:56 +0200 (CEST) Subject: [pypy-svn] r75068 - pypy/branch/unfreeze-encodings/pypy/module/sys Message-ID: <20100603175156.56601282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 19:51:54 2010 New Revision: 75068 Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Log: Add another assert. Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Thu Jun 3 19:51:54 2010 @@ -18,6 +18,8 @@ space.sys.defaultencoding = encoding def get_w_default_encoder(space): + assert not (space.config.translating and not we_are_translated()), \ + "get_w_default_encoder() should not be called during translation" w_encoding = space.wrap(space.sys.defaultencoding) mod = space.getbuiltinmodule("_codecs") w_lookup = space.getattr(mod, space.wrap("lookup")) From afa at codespeak.net Thu Jun 3 19:57:11 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 3 Jun 2010 19:57:11 +0200 (CEST) Subject: [pypy-svn] r75069 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100603175711.68819282BD6@codespeak.net> Author: afa Date: Thu Jun 3 19:57:09 2010 New Revision: 75069 Added: pypy/trunk/pypy/module/cpyext/test/test_translate.py Modified: pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/slotdefs.py pypy/trunk/pypy/module/cpyext/test/test_typeobject.py pypy/trunk/pypy/module/cpyext/typeobject.py Log: Various hacks to correctly expose different tp_function slots for different builtin types. For now only tp_setattro is correctly set, more refactoring will be needed, but this code *works*. llhelper() is really hard to use. Also fix more issues, now the differents variables and structure should be correctly exported, without the nasty #defines we had before. Boost.Python segfaults a bit later (in test_getting_started2.py) Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Thu Jun 3 19:57:09 2010 @@ -11,6 +11,7 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rlib.objectmodel import we_are_translated from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.gensupp import NameManager from pypy.tool.udir import udir from pypy.translator import platform from pypy.module.cpyext.state import State @@ -125,14 +126,18 @@ # the error value specifed in the API. # +cpyext_namespace = NameManager('cpyext_') + class ApiFunction: - def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED): + def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, + c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error + self.c_name = c_name # extract the signature from the (CPython-level) code object from pypy.interpreter import pycode @@ -159,6 +164,8 @@ wrapper = make_wrapper(space, self.callable) self._wrapper = wrapper wrapper.relax_sig_check = True + if self.c_name is not None: + wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): @@ -182,11 +189,16 @@ def decorate(func): func_name = func.func_name - api_function = ApiFunction(argtypes, restype, func, error) + if external: + c_name = None + else: + c_name = func_name + api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) func.api_func = api_function - assert func_name not in FUNCTIONS, "%s already registered" % func_name - assert func_name not in FUNCTIONS_STATIC + if external: + assert func_name not in FUNCTIONS, ( + "%s already registered" % func_name) if error is _NOT_SPECIFIED: raise ValueError("function %s has no return value for exceptions" @@ -261,8 +273,6 @@ unwrapper_raise = make_unwrapper(False) if external: FUNCTIONS[func_name] = api_function - else: - FUNCTIONS_STATIC[func_name] = api_function INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests return unwrapper_raise # used in 'normal' RPython code. return decorate @@ -277,7 +287,6 @@ INTERPLEVEL_API = {} FUNCTIONS = {} -FUNCTIONS_STATIC = {} SYMBOLS_C = [ 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse', 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords', @@ -439,6 +448,7 @@ # Make the wrapper for the cases (1) and (2) def make_wrapper(space, callable): + "NOT_RPYTHON" names = callable.api_func.argnames argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, [name.startswith("w_") for name in names]))) @@ -572,6 +582,7 @@ # back into Pypy space functions # Do not call this more than once per process def build_bridge(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -601,7 +612,10 @@ for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - global_objects.append('%s %s = NULL;' % (typ, name)) + if name.startswith('PyExc_'): + global_objects.append('%s %s;' % (typ[:-1], '_' + name)) + else: + global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -621,7 +635,6 @@ # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) - pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # populate static data for name, (typ, expr) in GLOBALS.iteritems(): @@ -632,6 +645,9 @@ isptr = False else: isptr = True + if name.startswith('PyExc_'): + isptr = False + INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') @@ -640,8 +656,13 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge,name) - py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) + if name.startswith('PyPyExc_'): + # we already have the pointer + py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) + else: + # we have a structure, get its address + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) w_type = space.type(w_obj) @@ -654,8 +675,12 @@ else: assert False, "Unknown static object: %s %s" % (typ, name) + pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') + # implement structure initialization code for name, func in FUNCTIONS.iteritems(): + if name.startswith('cpyext_'): # XXX hack + continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) @@ -666,6 +691,7 @@ return modulename.new(ext='') def generate_macros(export_symbols, rename=True, do_deref=True): + "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] for name in export_symbols: @@ -679,6 +705,8 @@ if not rename: newname = name pypy_macros.append('#define %s %s' % (name, newname)) + if name.startswith("PyExc_"): + pypy_macros.append('#define _%s _%s' % (name, newname)) renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols @@ -700,6 +728,7 @@ pypy_macros_h.write('\n'.join(pypy_macros)) def generate_decls_and_callbacks(db, export_symbols, api_struct=True): + "NOT_RPYTHON" # implement function callbacks and generate function decls functions = [] pypy_decls = [] @@ -734,6 +763,8 @@ if name.endswith('#'): name = name.replace("#", "") typ = typ.replace("*", "") + elif name.startswith('PyExc_'): + typ = 'PyObject*' pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) pypy_decls.append("#ifdef __cplusplus") @@ -746,6 +777,7 @@ return functions def build_eci(building_bridge, export_symbols, code): + "NOT_RPYTHON" # Build code and get pointer to the structure kwds = {} export_symbols_eci = export_symbols[:] @@ -768,6 +800,9 @@ for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): structs.append('%s %s;' % (typ[:-1], name[:-1])) + elif name.startswith('PyExc_'): + structs.append('extern PyTypeObject _%s;' % (name,)) + structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -793,6 +828,7 @@ def setup_library(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -812,6 +848,8 @@ # populate static data for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") + if name.startswith('PyExc_'): + name = '_' + name from pypy.module import cpyext w_obj = eval(expr) struct_ptr = make_ref(space, w_obj) @@ -822,8 +860,6 @@ for name, func in FUNCTIONS.iteritems(): deco = entrypoint("cpyext", func.argtypes, name, relax=True) deco(func.get_wrapper(space)) - for name, func in FUNCTIONS_STATIC.iteritems(): - func.get_wrapper(space).c_name = name setup_init_functions(eci) copy_header_files() Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/slotdefs.py (original) +++ pypy/trunk/pypy/module/cpyext/slotdefs.py Thu Jun 3 19:57:09 2010 @@ -12,8 +12,9 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.argument import Arguments from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name - +from pypy.rlib.objectmodel import specialize +from pypy.tool.sourcetools import func_renamer +from pypy.rpython.annlowlevel import llhelper # XXX: Also defined in object.h Py_LT = 0 @@ -177,19 +178,57 @@ def slot_nb_int(space, w_self): return space.int(w_self) - at cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1, external=False) -def slot_tp_setattro(space, w_self, w_name, w_value): - # XXX this is probably wrong when a subtype's tp_setattro - # delegates to PyType_Type.tp_setattro! - if w_value is not None: - space.setattr(w_self, w_name, w_value) +from pypy.rlib.nonconst import NonConstant + +SLOTS = {} + + at specialize.memo() +def get_slot_tp_function(space, typedef, name): + key = (typedef, name) + try: + return SLOTS[key] + except KeyError: + ret = build_slot_tp_function(space, typedef, name) + SLOTS[key] = ret + return ret + +def build_slot_tp_function(space, typedef, name): + w_type = space.gettypeobject(typedef) + + if name == 'tp_setattro': + setattr_fn = w_type.getdictvalue(space, '__setattr__') + delattr_fn = w_type.getdictvalue(space, '__delattr__') + if setattr_fn is None: + return + + @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, + error=-1, external=True) # XXX should not be exported + @func_renamer("cpyext_tp_setattro_%s" % (typedef.name,)) + def slot_tp_setattro(space, w_self, w_name, w_value): + if w_value is not None: + space.call_function(setattr_fn, w_self, w_name, w_value) + else: + space.call_function(delattr_fn, w_self, w_name) + return 0 + api_func = slot_tp_setattro.api_func else: - space.delattr(w_self, w_name) - return 0 + return + + return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) PyWrapperFlag_KEYWORDS = 1 -# adopted from typeobject.c +class TypeSlot: + def __init__(self, method_name, slot_name, function, wrapper1, wrapper2, doc): + self.method_name = method_name + self.slot_name = slot_name + self.slot_names = ("c_" + slot_name).split(".") + self.slot_func = function + self.wrapper_func = wrapper1 + self.wrapper_func_kwds = wrapper2 + self.doc = doc + +# adapted from typeobject.c def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS): if WRAPPER is None: wrapper = None @@ -201,23 +240,22 @@ wrapper = wrap_getattr function = globals().get(FUNCTION, None) - slotname = ("c_" + SLOT).split(".") assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func, w_kwds): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = None wrapper2 = wrapper else: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = wrapper wrapper2 = None - return (NAME, slotname, function, wrapper1, wrapper2, DOC) + return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC): return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0) @@ -470,7 +508,12 @@ for regex, repl in slotdef_replacements: slotdefs_str = re.sub(regex, repl, slotdefs_str) -slotdefs = unrolling_iterable(eval(slotdefs_str)) +slotdefs_for_tp_slots = unrolling_iterable( + [(x.method_name, x.slot_name, x.slot_names, x.slot_func) + for x in eval(slotdefs_str)]) +slotdefs_for_wrappers = unrolling_iterable( + [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) + for x in eval(slotdefs_str)]) if __name__ == "__main__": print slotdefs_str Added: pypy/trunk/pypy/module/cpyext/test/test_translate.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/cpyext/test/test_translate.py Thu Jun 3 19:57:09 2010 @@ -0,0 +1,71 @@ +from pypy.translator.c.test.test_genc import compile +import pypy.module.cpyext.api +from pypy.module.cpyext.api import cpython_api +from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.lltypesystem import lltype +from pypy.rlib.objectmodel import specialize +from pypy.rlib.nonconst import NonConstant + +def test_llhelper(monkeypatch): + """Show how to get function pointers used in type slots""" + FT = lltype.FuncType([], lltype.Signed) + FTPTR = lltype.Ptr(FT) + + def make_wrapper(space, func): + def wrapper(): + return func(space) + return wrapper + monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper) + + @specialize.memo() + def get_tp_function(space, typedef): + @cpython_api([], lltype.Signed, error=-1, external=False) + def slot_tp_function(space): + return typedef.value + + api_func = slot_tp_function.api_func + return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) + + class Space: + _cache = {} + @specialize.memo() + def fromcache(self, key): + try: + return self._cache[key] + except KeyError: + result = self._cache[key] = self.build(key) + return result + def _freeze_(self): + return True + class TypeDef: + def __init__(self, value): + self.value = value + def _freeze_(self): + return True + class W_Type: + def __init__(self, typedef): + self.instancetypedef = typedef + def _freeze(self): + try: + del self.funcptr + except AttributeError: + pass + return False + + w_type1 = W_Type(TypeDef(123)) + w_type2 = W_Type(TypeDef(456)) + space = Space() + + def run(x): + if x: + w_type = w_type1 + else: + w_type = w_type2 + typedef = w_type.instancetypedef + w_type.funcptr = get_tp_function(space, typedef)() + return w_type.funcptr() + + fn = compile(run, [bool]) + assert fn(True) == 123 + assert fn(False) == 456 + Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Thu Jun 3 19:57:09 2010 @@ -240,11 +240,17 @@ PyErr_SetString(PyExc_ValueError, "missing tp_setattro"); return NULL; } + if (args->ob_type->tp_setattro == + args->ob_type->tp_base->tp_setattro) + { + PyErr_SetString(PyExc_ValueError, "recursive tp_setattro"); + return NULL; + } Py_RETURN_TRUE; ''' ) ]) - assert module.test_type(None) + assert module.test_type(type(None)) def test_nb_int(self): module = self.import_extension('foo', [ Modified: pypy/trunk/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/typeobject.py Thu Jun 3 19:57:09 2010 @@ -25,7 +25,8 @@ from pypy.module.cpyext.typeobjectdefs import ( PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, PyNumberMethods) -from pypy.module.cpyext.slotdefs import slotdefs +from pypy.module.cpyext.slotdefs import ( + slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function) from pypy.interpreter.error import OperationError from pypy.rlib.rstring import rsplit from pypy.rlib.objectmodel import specialize @@ -102,48 +103,60 @@ def update_all_slots(space, w_type, pto): # XXX fill slots in pto - for method_name, slot_name, slot_func, _, _, _ in slotdefs: + + typedef = w_type.instancetypedef + for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: w_descr = w_type.lookup(method_name) if w_descr is None: # XXX special case iternext continue - if slot_func is None: + + slot_func_helper = None + + if slot_func is None and typedef is not None: + get_slot = get_slot_tp_function(space, typedef, slot_name) + if get_slot: + slot_func_helper = get_slot() + elif slot_func: + slot_func_helper = llhelper(slot_func.api_func.functype, + slot_func.api_func.get_wrapper(space)) + + if slot_func_helper is None: if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: os.write(2, method_name + " defined by the type but no slot function defined!\n") continue - slot_func_helper = llhelper(slot_func.api_func.functype, - slot_func.api_func.get_wrapper(space)) + # XXX special case wrapper-functions and use a "specific" slot func - if len(slot_name) == 1: - setattr(pto, slot_name[0], slot_func_helper) + if len(slot_names) == 1: + setattr(pto, slot_names[0], slot_func_helper) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: - if slot_name[0] == 'c_tp_as_number': + if slot_names[0] == 'c_tp_as_number': STRUCT_TYPE = PyNumberMethods else: raise AssertionError( - "Structure not allocated: %s" % (slot_name[0],)) + "Structure not allocated: %s" % (slot_names[0],)) struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) - setattr(pto, slot_name[0], struct) + setattr(pto, slot_names[0], struct) - setattr(struct, slot_name[1], slot_func_helper) + setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): # XXX support PyObject_HashNotImplemented - for method_name, slot_name, _, wrapper_func, wrapper_func_kwds, doc in slotdefs: + for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue - if len(slot_name) == 1: - func = getattr(pto, slot_name[0]) + if len(slot_names) == 1: + func = getattr(pto, slot_names[0]) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: continue - func = getattr(struct, slot_name[1]) + func = getattr(struct, slot_names[1]) func_voidp = rffi.cast(rffi.VOIDP_real, func) if not func: continue @@ -494,6 +507,8 @@ # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free + if not pto.c_tp_setattro: + pto.c_tp_setattro = base.c_tp_setattro finally: Py_DecRef(space, base_pyo) @@ -558,6 +573,12 @@ for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): inherit_slots(space, pto, w_base) + if not pto.c_tp_setattro: + from pypy.module.cpyext.object import PyObject_GenericSetAttr + pto.c_tp_setattro = llhelper( + PyObject_GenericSetAttr.api_func.functype, + PyObject_GenericSetAttr.api_func.get_wrapper(space)) + @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. From arigo at codespeak.net Thu Jun 3 20:07:22 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 20:07:22 +0200 (CEST) Subject: [pypy-svn] r75070 - in pypy/trunk/pypy/rlib: . test Message-ID: <20100603180722.AB854282BD6@codespeak.net> Author: arigo Date: Thu Jun 3 20:07:19 2010 New Revision: 75070 Modified: pypy/trunk/pypy/rlib/rarithmetic.py pypy/trunk/pypy/rlib/test/test_rarithmetic.py Log: Merge branch/int_is_not_intmask: removes the __int__() in class base_int(long), which returns an integer of a different value than 'self'. That causes surprizes, e.g. doing '%d' % x actually call x.__int__() on PyPy but not on CPython. I think that both behaviors are acceptable -- on PyPy we generally call __xyz__() methods more often than CPython does. Modified: pypy/trunk/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/trunk/pypy/rlib/rarithmetic.py (original) +++ pypy/trunk/pypy/rlib/rarithmetic.py Thu Jun 3 20:07:19 2010 @@ -178,12 +178,6 @@ else: return super(base_int, klass).__new__(klass, val) - def __int__(self): - if self < LONG_TEST: - return long.__int__(self) - else: - return intmask(self) - def __add__(self, other): x = long(self) y = long(other) Modified: pypy/trunk/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/trunk/pypy/rlib/test/test_rarithmetic.py Thu Jun 3 20:07:19 2010 @@ -114,7 +114,10 @@ #self.binary_test(lambda x, y: pow(x, y, 42), (2, 3, 5, 1000)) def test_back_to_int(self): - assert int(r_uint(-1)) == -1 + #assert int(r_uint(-1)) == -1 + # ^^^ that looks wrong IMHO: int(x) should not by itself return + # an integer that has a different value than x, especially + # if x is a subclass of long. assert int(r_uint(1)) == 1 def unary_test(self, f): From arigo at codespeak.net Thu Jun 3 20:07:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jun 2010 20:07:34 +0200 (CEST) Subject: [pypy-svn] r75071 - pypy/branch/int_is_not_intmask Message-ID: <20100603180734.C721C36C394@codespeak.net> Author: arigo Date: Thu Jun 3 20:07:31 2010 New Revision: 75071 Removed: pypy/branch/int_is_not_intmask/ Log: Remove merged branch. From benjamin at codespeak.net Thu Jun 3 20:12:02 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 20:12:02 +0200 (CEST) Subject: [pypy-svn] r75072 - pypy/branch/fast-forward/pypy/module/sys Message-ID: <20100603181202.37C0A282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 20:12:00 2010 New Revision: 75072 Modified: pypy/branch/fast-forward/pypy/module/sys/state.py Log: allow for a modified lib not to exist Modified: pypy/branch/fast-forward/pypy/module/sys/state.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/state.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/state.py Thu Jun 3 20:12:00 2010 @@ -45,14 +45,21 @@ python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) - checkdir(python_std_lib_modified) + have_modified = True + try: + checkdir(python_std_lib_modified) + except OSError, e: + if e.errno != errno.ENOENT: + raise + have_modified = False pypydir = os.path.join(srcdir, 'pypy') pypy_lib = os.path.join(pypydir, 'lib') checkdir(pypy_lib) importlist = [] importlist.append(pypy_lib) - importlist.append(python_std_lib_modified) + if have_modified: + importlist.append(python_std_lib_modified) importlist.append(python_std_lib) return importlist From benjamin at codespeak.net Thu Jun 3 20:49:40 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 20:49:40 +0200 (CEST) Subject: [pypy-svn] r75073 - in pypy/branch/fast-forward/pypy: interpreter/pyparser interpreter/pyparser/test module/__builtin__ module/__builtin__/test Message-ID: <20100603184940.C5016282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 20:49:37 2010 New Revision: 75073 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenize.py pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Log: alias bytes to str and implement b syntax Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py Thu Jun 3 20:49:37 2010 @@ -17,7 +17,10 @@ o = ord(quote) isalpha = (o>=97 and o<=122) or (o>=65 and o<=90) if isalpha or quote == '_': - if quote == 'u' or quote == 'U': + if quote == 'b' or quote == 'B': + ps += 1 + quote = s[ps] + elif quote == 'u' or quote == 'U': ps += 1 quote = s[ps] unicode = True Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pytokenize.py Thu Jun 3 20:49:37 2010 @@ -38,7 +38,7 @@ '7': 5, '8': 5, '9': 5, ':': 13, ';': 13, '<': 9, '=': 12, '>': 8, '@': 13, 'A': 1, - 'B': 1, 'C': 1, 'D': 1, 'E': 1, + 'B': 3, 'C': 1, 'D': 1, 'E': 1, 'F': 1, 'G': 1, 'H': 1, 'I': 1, 'J': 1, 'K': 1, 'L': 1, 'M': 1, 'N': 1, 'O': 1, 'P': 1, 'Q': 1, @@ -46,7 +46,7 @@ 'V': 1, 'W': 1, 'X': 1, 'Y': 1, 'Z': 1, '[': 13, '\\': 17, ']': 13, '^': 12, '_': 1, '`': 13, 'a': 1, - 'b': 1, 'c': 1, 'd': 1, 'e': 1, + 'b': 3, 'c': 1, 'd': 1, 'e': 1, 'f': 1, 'g': 1, 'h': 1, 'i': 1, 'j': 1, 'k': 1, 'l': 1, 'm': 1, 'n': 1, 'o': 1, 'p': 1, 'q': 1, @@ -284,15 +284,21 @@ for t in ("'''", '"""', "r'''", 'r"""', "R'''", 'R"""', "u'''", 'u"""', "U'''", 'U"""', + "b'''", 'b"""', "B'''", 'B"""', "ur'''", 'ur"""', "Ur'''", 'Ur"""', - "uR'''", 'uR"""', "UR'''", 'UR"""'): + "uR'''", 'uR"""', "UR'''", 'UR"""', + "br'''", 'br"""', "Br'''", 'Br"""', + "bR'''", 'bR"""', "BR'''", 'BR"""'): triple_quoted[t] = t single_quoted = {} for t in ("'", '"', "r'", 'r"', "R'", 'R"', "u'", 'u"', "U'", 'U"', + "b'", 'b"', "B'", 'B"', "ur'", 'ur"', "Ur'", 'Ur"', - "uR'", 'uR"', "UR'", 'UR"' ): + "uR'", 'uR"', "UR'", 'UR"', + "br'", 'br"', "Br'", 'Br"', + "bR'", 'bR"', "BR'", 'BR"'): single_quoted[t] = t tabsize = 8 @@ -314,3 +320,4 @@ # ______________________________________________________________________ # End of pytokenize.py + Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py Thu Jun 3 20:49:37 2010 @@ -67,7 +67,16 @@ s = s.decode("koi8-u").encode("utf8") w_ret = parsestring.parsestr(self.space, 'koi8-u', s) ret = space.unwrap(w_ret) - assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") + assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") + + def test_bytes(self): + space = self.space + b = "b'hello'" + w_ret = parsestring.parsestr(space, None, b) + assert space.unwrap(w_ret) == "hello" + b = "b'''hello'''" + w_ret = parsestring.parsestr(space, None, b) + assert space.unwrap(w_ret) == "hello" def test_simple_enc_roundtrip(self): #py.test.skip("crashes in app_codecs, but when cheating using .encode at interp-level passes?!") Modified: pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py Thu Jun 3 20:49:37 2010 @@ -47,6 +47,7 @@ '__debug__' : '(space.w_True)', # XXX 'type' : '(space.w_type)', 'object' : '(space.w_object)', + 'bytes' : '(space.w_str)', 'unicode' : '(space.w_unicode)', 'buffer' : 'operation.Buffer', Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Thu Jun 3 20:49:37 2010 @@ -16,6 +16,10 @@ except KeyError: cls.w_sane_lookup = cls.space.wrap(False) + def test_bytes_alias(self): + assert bytes is str + assert isinstance(eval("b'hi'"), str) + def test_import(self): m = __import__('pprint') assert m.pformat({}) == '{}' From benjamin at codespeak.net Thu Jun 3 21:00:21 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 21:00:21 +0200 (CEST) Subject: [pypy-svn] r75074 - pypy/branch/fast-forward/pypy/module/sys Message-ID: <20100603190021.45988282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 21:00:18 2010 New Revision: 75074 Modified: pypy/branch/fast-forward/pypy/module/sys/state.py pypy/branch/fast-forward/pypy/module/sys/version.py Log: move the cpython lib dirname out of a function Modified: pypy/branch/fast-forward/pypy/module/sys/state.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/state.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/state.py Thu Jun 3 21:00:18 2010 @@ -4,6 +4,7 @@ import pypy from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace +from pypy.module.sys import version import sys, os, stat, errno @@ -35,12 +36,8 @@ def getinitialpath(srcdir): # build the initial path from the srcdir, which is the path of # the "dist" directory of a PyPy checkout. - from pypy.module.sys.version import CPYTHON_VERSION - - dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], - CPYTHON_VERSION[1], - CPYTHON_VERSION[2]) lib_python = os.path.join(srcdir, 'lib-python') + dirname = version.CPYTHON_VERSION_DIR python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) Modified: pypy/branch/fast-forward/pypy/module/sys/version.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/version.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/version.py Thu Jun 3 21:00:18 2010 @@ -6,6 +6,10 @@ CPYTHON_VERSION = (2, 7, 0, "beta", 42) CPYTHON_API_VERSION = 1012 +CPYTHON_VERSION_DIR = '%d.%d.%d' % (CPYTHON_VERSION[0], + CPYTHON_VERSION[1], + CPYTHON_VERSION[2]) + PYPY_VERSION = (1, 2, 0, "beta", '?') # the last item is replaced by the svn revision ^^^ From benjamin at codespeak.net Thu Jun 3 21:05:07 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 21:05:07 +0200 (CEST) Subject: [pypy-svn] r75075 - pypy/branch/fast-forward/pypy/tool Message-ID: <20100603190507.41E20282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 21:04:34 2010 New Revision: 75075 Modified: pypy/branch/fast-forward/pypy/tool/stdlib___future__.py Log: make __future__ be loaded from correct dir Modified: pypy/branch/fast-forward/pypy/tool/stdlib___future__.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/stdlib___future__.py (original) +++ pypy/branch/fast-forward/pypy/tool/stdlib___future__.py Thu Jun 3 21:04:34 2010 @@ -2,7 +2,9 @@ def load_module(): import py - module_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/2.5.2/__future__.py') + from pypy.module.sys.version import CPYTHON_VERSION_DIR + to_future = "lib-python/%s/__future__.py" % (CPYTHON_VERSION_DIR,) + module_path = py.path.local(__file__).dirpath().dirpath().dirpath(to_future) execfile(str(module_path), globals()) load_module() From fijall at gmail.com Thu Jun 3 21:07:48 2010 From: fijall at gmail.com (Maciej Fijalkowski) Date: Thu, 3 Jun 2010 13:07:48 -0600 Subject: [pypy-svn] r75069 - in pypy/trunk/pypy/module/cpyext: . test In-Reply-To: <20100603175711.68819282BD6@codespeak.net> References: <20100603175711.68819282BD6@codespeak.net> Message-ID: On Thu, Jun 3, 2010 at 11:57 AM, wrote: > Author: afa > Date: Thu Jun ?3 19:57:09 2010 > New Revision: 75069 > > Added: > ? pypy/trunk/pypy/module/cpyext/test/test_translate.py > Modified: > ? pypy/trunk/pypy/module/cpyext/api.py > ? pypy/trunk/pypy/module/cpyext/slotdefs.py > ? pypy/trunk/pypy/module/cpyext/test/test_typeobject.py > ? pypy/trunk/pypy/module/cpyext/typeobject.py > Log: > Various hacks to correctly expose different tp_function slots for different builtin types. > For now only tp_setattro is correctly set, > more refactoring will be needed, but this code *works*. > > llhelper() is really hard to use. There is a reason why it was not meant to be used for translations. ? ? if WRAPPER is None: > ? ? ? ? wrapper = None > @@ -201,23 +240,22 @@ > ? ? ? ? wrapper = wrap_getattr > > ? ? function = globals().get(FUNCTION, None) > - ? ?slotname = ("c_" + SLOT).split(".") > ? ? assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS > ? ? if FLAGS: > ? ? ? ? if wrapper is Ellipsis: > + ? ? ? ? ? ?@func_renamer(WRAPPER) > ? ? ? ? ? ? def wrapper(space, w_self, w_args, func, w_kwds): > ? ? ? ? ? ? ? ? raise NotImplementedError("Wrapper for slot " + NAME) > - ? ? ? ? ? ?wrapper = func_with_new_name(wrapper, WRAPPER) > ? ? ? ? wrapper1 = None > ? ? ? ? wrapper2 = wrapper > ? ? else: > ? ? ? ? if wrapper is Ellipsis: > + ? ? ? ? ? ?@func_renamer(WRAPPER) > ? ? ? ? ? ? def wrapper(space, w_self, w_args, func): > ? ? ? ? ? ? ? ? raise NotImplementedError("Wrapper for slot " + NAME) > - ? ? ? ? ? ?wrapper = func_with_new_name(wrapper, WRAPPER) > ? ? ? ? wrapper1 = wrapper > ? ? ? ? wrapper2 = None > - ? ?return (NAME, slotname, function, wrapper1, wrapper2, DOC) > + ? ?return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) > > ?def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC): > ? ? return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0) > @@ -470,7 +508,12 @@ > ?for regex, repl in slotdef_replacements: > ? ? slotdefs_str = re.sub(regex, repl, slotdefs_str) > > -slotdefs = unrolling_iterable(eval(slotdefs_str)) > +slotdefs_for_tp_slots = unrolling_iterable( > + ? ?[(x.method_name, x.slot_name, x.slot_names, x.slot_func) > + ? ? for x in eval(slotdefs_str)]) > +slotdefs_for_wrappers = unrolling_iterable( > + ? ?[(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) > + ? ? for x in eval(slotdefs_str)]) > > ?if __name__ == "__main__": > ? ? print slotdefs_str > > Added: pypy/trunk/pypy/module/cpyext/test/test_translate.py > ============================================================================== > --- (empty file) > +++ pypy/trunk/pypy/module/cpyext/test/test_translate.py ? ? ? ?Thu Jun ?3 19:57:09 2010 > @@ -0,0 +1,71 @@ > +from pypy.translator.c.test.test_genc import compile > +import pypy.module.cpyext.api > +from pypy.module.cpyext.api import cpython_api > +from pypy.rpython.annlowlevel import llhelper > +from pypy.rpython.lltypesystem import lltype > +from pypy.rlib.objectmodel import specialize > +from pypy.rlib.nonconst import NonConstant > + > +def test_llhelper(monkeypatch): > + ? ?"""Show how to get function pointers used in type slots""" > + ? ?FT = lltype.FuncType([], lltype.Signed) > + ? ?FTPTR = lltype.Ptr(FT) > + > + ? ?def make_wrapper(space, func): > + ? ? ? ?def wrapper(): > + ? ? ? ? ? ?return func(space) > + ? ? ? ?return wrapper > + ? ?monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper) > + > + ? ?@specialize.memo() > + ? ?def get_tp_function(space, typedef): > + ? ? ? ?@cpython_api([], lltype.Signed, error=-1, external=False) > + ? ? ? ?def slot_tp_function(space): > + ? ? ? ? ? ?return typedef.value > + > + ? ? ? ?api_func = slot_tp_function.api_func > + ? ? ? ?return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) > + > + ? ?class Space: > + ? ? ? ?_cache = {} > + ? ? ? ?@specialize.memo() > + ? ? ? ?def fromcache(self, key): > + ? ? ? ? ? ?try: > + ? ? ? ? ? ? ? ?return self._cache[key] > + ? ? ? ? ? ?except KeyError: > + ? ? ? ? ? ? ? ?result = self._cache[key] = self.build(key) > + ? ? ? ? ? ? ? ?return result > + ? ? ? ?def _freeze_(self): > + ? ? ? ? ? ?return True > + ? ?class TypeDef: > + ? ? ? ?def __init__(self, value): > + ? ? ? ? ? ?self.value = value > + ? ? ? ?def _freeze_(self): > + ? ? ? ? ? ?return True > + ? ?class W_Type: > + ? ? ? ?def __init__(self, typedef): > + ? ? ? ? ? ?self.instancetypedef = typedef > + ? ? ? ?def _freeze(self): > + ? ? ? ? ? ?try: > + ? ? ? ? ? ? ? ?del self.funcptr > + ? ? ? ? ? ?except AttributeError: > + ? ? ? ? ? ? ? ?pass > + ? ? ? ? ? ?return False > + > + ? ?w_type1 = W_Type(TypeDef(123)) > + ? ?w_type2 = W_Type(TypeDef(456)) > + ? ?space = Space() > + > + ? ?def run(x): > + ? ? ? ?if x: > + ? ? ? ? ? ?w_type = w_type1 > + ? ? ? ?else: > + ? ? ? ? ? ?w_type = w_type2 > + ? ? ? ?typedef = w_type.instancetypedef > + ? ? ? ?w_type.funcptr = get_tp_function(space, typedef)() > + ? ? ? ?return w_type.funcptr() > + > + ? ?fn = compile(run, [bool]) > + ? ?assert fn(True) == 123 > + ? ?assert fn(False) == 456 > + > > Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py > ============================================================================== > --- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ? ? ? (original) > +++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ? ? ? Thu Jun ?3 19:57:09 2010 > @@ -240,11 +240,17 @@ > ? ? ? ? ? ? ? ? ? ? ?PyErr_SetString(PyExc_ValueError, "missing tp_setattro"); > ? ? ? ? ? ? ? ? ? ? ?return NULL; > ? ? ? ? ? ? ? ? ?} > + ? ? ? ? ? ? ? ? if (args->ob_type->tp_setattro == > + ? ? ? ? ? ? ? ? ? ? args->ob_type->tp_base->tp_setattro) > + ? ? ? ? ? ? ? ? { > + ? ? ? ? ? ? ? ? ? ? PyErr_SetString(PyExc_ValueError, "recursive tp_setattro"); > + ? ? ? ? ? ? ? ? ? ? return NULL; > + ? ? ? ? ? ? ? ? } > ? ? ? ? ? ? ? ? ?Py_RETURN_TRUE; > ? ? ? ? ? ? ?''' > ? ? ? ? ? ? ?) > ? ? ? ? ? ? ]) > - ? ? ? ?assert module.test_type(None) > + ? ? ? ?assert module.test_type(type(None)) > > ? ? def test_nb_int(self): > ? ? ? ? module = self.import_extension('foo', [ > > Modified: pypy/trunk/pypy/module/cpyext/typeobject.py > ============================================================================== > --- pypy/trunk/pypy/module/cpyext/typeobject.py (original) > +++ pypy/trunk/pypy/module/cpyext/typeobject.py Thu Jun ?3 19:57:09 2010 > @@ -25,7 +25,8 @@ > ?from pypy.module.cpyext.typeobjectdefs import ( > ? ? PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, > ? ? PyNumberMethods) > -from pypy.module.cpyext.slotdefs import slotdefs > +from pypy.module.cpyext.slotdefs import ( > + ? ?slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function) > ?from pypy.interpreter.error import OperationError > ?from pypy.rlib.rstring import rsplit > ?from pypy.rlib.objectmodel import specialize > @@ -102,48 +103,60 @@ > > ?def update_all_slots(space, w_type, pto): > ? ? # ?XXX fill slots in pto > - ? ?for method_name, slot_name, slot_func, _, _, _ in slotdefs: > + > + ? ?typedef = w_type.instancetypedef > + ? ?for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: > ? ? ? ? w_descr = w_type.lookup(method_name) > ? ? ? ? if w_descr is None: > ? ? ? ? ? ? # XXX special case iternext > ? ? ? ? ? ? continue > - ? ? ? ?if slot_func is None: > + > + ? ? ? ?slot_func_helper = None > + > + ? ? ? ?if slot_func is None and typedef is not None: > + ? ? ? ? ? ?get_slot = get_slot_tp_function(space, typedef, slot_name) > + ? ? ? ? ? ?if get_slot: > + ? ? ? ? ? ? ? ?slot_func_helper = get_slot() > + ? ? ? ?elif slot_func: > + ? ? ? ? ? ?slot_func_helper = llhelper(slot_func.api_func.functype, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?slot_func.api_func.get_wrapper(space)) > + > + ? ? ? ?if slot_func_helper is None: > ? ? ? ? ? ? if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: > ? ? ? ? ? ? ? ? os.write(2, method_name + " defined by the type but no slot function defined!\n") > ? ? ? ? ? ? continue > - ? ? ? ?slot_func_helper = llhelper(slot_func.api_func.functype, > - ? ? ? ? ? ? ? ?slot_func.api_func.get_wrapper(space)) > + > ? ? ? ? # XXX special case wrapper-functions and use a "specific" slot func > > - ? ? ? ?if len(slot_name) == 1: > - ? ? ? ? ? ?setattr(pto, slot_name[0], slot_func_helper) > + ? ? ? ?if len(slot_names) == 1: > + ? ? ? ? ? ?setattr(pto, slot_names[0], slot_func_helper) > ? ? ? ? else: > - ? ? ? ? ? ?assert len(slot_name) == 2 > - ? ? ? ? ? ?struct = getattr(pto, slot_name[0]) > + ? ? ? ? ? ?assert len(slot_names) == 2 > + ? ? ? ? ? ?struct = getattr(pto, slot_names[0]) > ? ? ? ? ? ? if not struct: > - ? ? ? ? ? ? ? ?if slot_name[0] == 'c_tp_as_number': > + ? ? ? ? ? ? ? ?if slot_names[0] == 'c_tp_as_number': > ? ? ? ? ? ? ? ? ? ? STRUCT_TYPE = PyNumberMethods > ? ? ? ? ? ? ? ? else: > ? ? ? ? ? ? ? ? ? ? raise AssertionError( > - ? ? ? ? ? ? ? ? ? ? ? ?"Structure not allocated: %s" % (slot_name[0],)) > + ? ? ? ? ? ? ? ? ? ? ? ?"Structure not allocated: %s" % (slot_names[0],)) > ? ? ? ? ? ? ? ? struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) > - ? ? ? ? ? ? ? ?setattr(pto, slot_name[0], struct) > + ? ? ? ? ? ? ? ?setattr(pto, slot_names[0], struct) > > - ? ? ? ? ? ?setattr(struct, slot_name[1], slot_func_helper) > + ? ? ? ? ? ?setattr(struct, slot_names[1], slot_func_helper) > > ?def add_operators(space, dict_w, pto): > ? ? # XXX support PyObject_HashNotImplemented > - ? ?for method_name, slot_name, _, wrapper_func, wrapper_func_kwds, doc in slotdefs: > + ? ?for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: > ? ? ? ? if method_name in dict_w: > ? ? ? ? ? ? continue > - ? ? ? ?if len(slot_name) == 1: > - ? ? ? ? ? ?func = getattr(pto, slot_name[0]) > + ? ? ? ?if len(slot_names) == 1: > + ? ? ? ? ? ?func = getattr(pto, slot_names[0]) > ? ? ? ? else: > - ? ? ? ? ? ?assert len(slot_name) == 2 > - ? ? ? ? ? ?struct = getattr(pto, slot_name[0]) > + ? ? ? ? ? ?assert len(slot_names) == 2 > + ? ? ? ? ? ?struct = getattr(pto, slot_names[0]) > ? ? ? ? ? ? if not struct: > ? ? ? ? ? ? ? ? continue > - ? ? ? ? ? ?func = getattr(struct, slot_name[1]) > + ? ? ? ? ? ?func = getattr(struct, slot_names[1]) > ? ? ? ? func_voidp = rffi.cast(rffi.VOIDP_real, func) > ? ? ? ? if not func: > ? ? ? ? ? ? continue > @@ -494,6 +507,8 @@ > ? ? ? ? # XXX check for correct GC flags! > ? ? ? ? if not pto.c_tp_free: > ? ? ? ? ? ? pto.c_tp_free = base.c_tp_free > + ? ? ? ?if not pto.c_tp_setattro: > + ? ? ? ? ? ?pto.c_tp_setattro = base.c_tp_setattro > ? ? finally: > ? ? ? ? Py_DecRef(space, base_pyo) > > @@ -558,6 +573,12 @@ > ? ? for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): > ? ? ? ? inherit_slots(space, pto, w_base) > > + ? ?if not pto.c_tp_setattro: > + ? ? ? ?from pypy.module.cpyext.object import PyObject_GenericSetAttr > + ? ? ? ?pto.c_tp_setattro = llhelper( > + ? ? ? ? ? ?PyObject_GenericSetAttr.api_func.functype, > + ? ? ? ? ? ?PyObject_GenericSetAttr.api_func.get_wrapper(space)) > + > ?@cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) > ?def PyType_IsSubtype(space, a, b): > ? ? """Return true if a is a subtype of b. > _______________________________________________ > pypy-svn mailing list > pypy-svn at codespeak.net > http://codespeak.net/mailman/listinfo/pypy-svn > From benjamin at codespeak.net Thu Jun 3 21:09:28 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 21:09:28 +0200 (CEST) Subject: [pypy-svn] r75076 - in pypy/branch/fast-forward/pypy/interpreter: . pyparser Message-ID: <20100603190928.DD0AA282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 21:08:57 2010 New Revision: 75076 Modified: pypy/branch/fast-forward/pypy/interpreter/pycompiler.py pypy/branch/fast-forward/pypy/interpreter/pyparser/future.py Log: use 2.7 future flags Modified: pypy/branch/fast-forward/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pycompiler.py Thu Jun 3 21:08:57 2010 @@ -103,7 +103,7 @@ PyCodeCompiler.__init__(self, space) self.parser = pyparse.PythonParser(space) self.additional_rules = {} - self.future_flags = future.futureFlags_2_5 + self.future_flags = future.futureFlags_2_7 self.compiler_flags = self.future_flags.allowed_flags def compile_ast(self, node, filename, mode, flags): Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/future.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/future.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/future.py Thu Jun 3 21:08:57 2010 @@ -318,3 +318,4 @@ futureFlags_2_4 = FutureFlags((2, 4, 4, 'final', 0)) futureFlags_2_5 = FutureFlags((2, 5, 0, 'final', 0)) +futureFlags_2_7 = FutureFlags((2, 7, 0, 'final', 0)) From benjamin at codespeak.net Thu Jun 3 21:10:51 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 21:10:51 +0200 (CEST) Subject: [pypy-svn] r75077 - in pypy/branch/fast-forward/pypy/interpreter: pyparser test Message-ID: <20100603191051.7BF24282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 21:10:31 2010 New Revision: 75077 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: the with statement is now always enabled Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py Thu Jun 3 21:10:31 2010 @@ -19,11 +19,6 @@ python_grammar = _get_python_grammar() -python_grammar_no_with_statement = python_grammar.shared_copy() -python_grammar_no_with_statement.keyword_ids = \ - python_grammar_no_with_statement.keyword_ids.copy() -del python_grammar_no_with_statement.keyword_ids["with"] -del python_grammar_no_with_statement.keyword_ids["as"] class _Tokens(object): pass Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py Thu Jun 3 21:10:31 2010 @@ -129,15 +129,7 @@ flags = compile_info.flags - # In order to not raise errors when 'as' or 'with' are used as names in - # code that does not explicitly enable the with statement, we have two - # grammars. One with 'as' and 'with' and keywords and one without. - # This is far better than CPython, where the parser is hacked up to - # check for __future__ imports and recognize new keywords accordingly. - if flags & consts.CO_FUTURE_WITH_STATEMENT: - self.grammar = pygram.python_grammar - else: - self.grammar = pygram.python_grammar_no_with_statement + self.grammar = pygram.python_grammar # The tokenizer is very picky about how it wants its input. source_lines = textsrc.splitlines(True) Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Thu Jun 3 21:10:31 2010 @@ -318,7 +318,7 @@ class AppTestWith: def test_with_simple(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -340,7 +340,6 @@ def test_start_with_blank_line(self): s = """ -from __future__ import with_statement if 1: class Context: def __init__(self): @@ -361,7 +360,6 @@ def test_raw_doc_string(self): s = """r'doc' -from __future__ import with_statement class Context(object): def __enter__(self): global enter @@ -377,7 +375,7 @@ def test_with_as_var(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -403,7 +401,7 @@ def test_with_raise_exception(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -438,7 +436,7 @@ def test_with_swallow_exception(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -469,7 +467,7 @@ def test_with_break(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -500,7 +498,7 @@ def test_with_continue(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -530,7 +528,7 @@ assert acontextfact.exit_params == (None, None, None) def test_with_return(self): - s = """from __future__ import with_statement + s = """ if 1: class Context: def __init__(self): @@ -558,20 +556,9 @@ assert acontextfact.calls == '__enter__ __body__ __exit__ __return__'.split() assert acontextfact.exit_params == (None, None, None) - def test_with_as_identifier(self): - exec "with = 9" - def test_with_as_keyword(self): try: - exec "from __future__ import with_statement\nwith = 9" - except SyntaxError: - pass - else: - assert False, 'Assignment to with did not raise SyntaxError' - - def test_with_as_keyword_and_docstring(self): - try: - exec "'Docstring'\nfrom __future__ import with_statement\nwith = 9" + exec "with = 9" except SyntaxError: pass else: @@ -585,33 +572,11 @@ else: assert False, 'Assignment to with did not raise SyntaxError' - def test_with_as_keyword_multiple(self): - try: - exec "from __future__ import generators\nfrom __future__ import with_statement\nwith = 9" - except SyntaxError: - pass - else: - assert False, 'Assignment to with did not raise SyntaxError' - - def test_as_as_identifier(self): - exec "as = 9" - exec "import sys as foo" - - def test_as_as_keyword(self): - try: - exec "from __future__ import with_statement\nas = 9" - except SyntaxError: - pass - else: - assert False, 'Assignment to as did not raise SyntaxError' - - exec "from __future__ import with_statement\nimport sys as foo" - def test_missing_as_SyntaxError(self): snippets = [ "import os.path a bar ", "from os import path a bar", - """from __future__ import with_statement + """ with foo a bar: pass """] @@ -625,7 +590,7 @@ def test_with_propagate_compileflag(self): - s = """from __future__ import with_statement + s = """ if 1: compile('''with x: pass''', '', 'exec') From benjamin at codespeak.net Thu Jun 3 21:20:16 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 21:20:16 +0200 (CEST) Subject: [pypy-svn] r75078 - in pypy/branch/fast-forward/pypy/module/sys: . test Message-ID: <20100603192016.D75B5282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 21:20:14 2010 New Revision: 75078 Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Log: add dummy sys.py3kwarning Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Thu Jun 3 21:20:14 2010 @@ -32,7 +32,8 @@ #'pypy_prefix': added by pypy_initial_path() when it succeeds, pointing # to the trunk of a checkout or to the dir /usr/share/pypy-1.1 . - 'path' : 'state.get(space).w_path', + 'path' : 'state.get(space).w_path', + 'py3kwarning' : 'space.w_False', # for now 'modules' : 'state.get(space).w_modules', 'argv' : 'state.get(space).w_argv', 'warnoptions' : 'state.get(space).w_warnoptions', Modified: pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Thu Jun 3 21:20:14 2010 @@ -26,7 +26,11 @@ def setup_class(cls): cls.w_appdirect = cls.space.wrap(option.runappdirect) cls.w_filesystemenc = cls.space.wrap(sys.getfilesystemencoding()) - + + def test_sys_py3kwarning(self): + import sys + assert not sys.py3kwarning + def test_sys_in_modules(self): import sys modules = sys.modules From benjamin at codespeak.net Thu Jun 3 22:37:57 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 22:37:57 +0200 (CEST) Subject: [pypy-svn] r75079 - in pypy/branch/fast-forward/pypy/translator/goal: . test2 Message-ID: <20100603203757.228C8282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 22:37:55 2010 New Revision: 75079 Modified: pypy/branch/fast-forward/pypy/translator/goal/app_main.py pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py Log: whack app_main so it at least accepts all 2.7 arguments Modified: pypy/branch/fast-forward/pypy/translator/goal/app_main.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/app_main.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/app_main.py Thu Jun 3 22:37:55 2010 @@ -236,28 +236,72 @@ return executable +default_options = dict.fromkeys(( + "debug", + "py3k_warning", + "inspect", + "interactive", + "optimize", + "no_user_site", + "ignore_environment", + "no_site", + "tabcheck", + "verbose", + "unicode", + "bytes_warning", + "dont_write_bytecode", + "run_command", + "run_module", + "run_stdin", + "warnoptions", + "unbuffered"), False) + + def parse_command_line(argv): - go_interactive = False - run_command = False - import_site = True + options = default_options.copy() + print_sys_flags = False i = 0 - run_module = False - run_stdin = False - warnoptions = [] - unbuffered = False while i < len(argv): arg = argv[i] if not arg.startswith('-'): break if arg == '-i': - go_interactive = True + options["inspect"] = options["interactive"] = True + elif arg == '-d': + options["debug"] = True + elif arg == '-3': + options["py3k_warning"] = True + elif arg == '-E': + options["ignore_environment"] = True + elif arg == '-U': + options["unicode"] = True + elif arg.startswith('-b'): + options["bytes_warning"] = arg.count('b') + elif arg.startswith('-t'): + options["tabcheck"] = arg.count('t') + elif arg.startswith('-v'): + options["verbose"] += arg.count('v') + elif arg.startswith('-Q'): + div, i = get_argument("-Q", argv, i) + if div == "warn": + options["division_warning"] = 1 + elif div == "warnall": + options["division_warning"] = 2 + elif div == "new": + options["division_new"] = True + elif div != "old": + raise CommandLineError("invalid division option: %r" % (div,)) + elif arg.startswith('-O'): + options["optimize"] = arg.count('O') + elif arg == '-B': + options["dont_write_bytecode"] = True elif arg.startswith('-c'): - cmd, i = get_argument('-c', argv, i) + options["cmd"], i = get_argument('-c', argv, i) argv[i] = '-c' - run_command = True + options["run_command"] = True break elif arg == '-u': - unbuffered = True + options["unbuffered"] = True elif arg == '-O': pass elif arg == '--version' or arg == '-V': @@ -269,18 +313,20 @@ elif arg == '-h' or arg == '--help': print_help() return + elif arg == '-s': + options["no_user_site"] = True elif arg == '-S': - import_site = False + options["no_site"] = True elif arg == '-': - run_stdin = True + options["run_stdin"] = True break # not an option but a file name representing stdin elif arg.startswith('-m'): module, i = get_argument('-m', argv, i) argv[i] = module - run_module = True + options["run_module"] = True break elif arg.startswith('-W'): - warnoptions, i = get_argument('-W', argv, i) + options["warnoptions"], i = get_argument('-W', argv, i) elif arg.startswith('--jit'): jitparam, i = get_argument('--jit', argv, i) if 'pypyjit' not in sys.builtin_module_names: @@ -291,19 +337,28 @@ pypyjit.set_param(jitparam) elif arg == '--': i += 1 - break # terminates option list + break # terminates option list + # for testing + elif not we_are_translated() and arg == "--print-sys-flags": + print_sys_flags = True else: raise CommandLineError('unrecognized option %r' % (arg,)) i += 1 sys.argv = argv[i:] if not sys.argv: sys.argv.append('') - run_stdin = True - return locals() + options["run_stdin"] = True + if print_sys_flags: + flag_opts = ["%s=%s" % (opt, int(value)) + for opt, value in options.iteritems() + if isinstance(value, int)] + "(%s)" % (", ".join(flag_opts),) + print flag_opts + return options -def run_command_line(go_interactive, +def run_command_line(interactive, run_command, - import_site, + no_site, run_module, run_stdin, warnoptions, @@ -323,7 +378,7 @@ mainmodule = type(sys)('__main__') sys.modules['__main__'] = mainmodule - if import_site: + if not no_site: try: import site except: @@ -352,12 +407,12 @@ def inspect_requested(): # We get an interactive prompt in one of the following two cases: # - # * go_interactive=True, either from the "-i" option or - # from the fact that we printed the banner; + # * insepct=True, either from the "-i" option or from the fact that + # we printed the banner; # or # * PYTHONINSPECT is set and stdin is a tty. # - return (go_interactive or + return (interactive or (os.getenv('PYTHONINSPECT') and sys.stdin.isatty())) success = True @@ -377,7 +432,7 @@ elif run_stdin: # handle the case where no command/filename/module is specified # on the command-line. - if go_interactive or sys.stdin.isatty(): + if interactive or sys.stdin.isatty(): # If stdin is a tty or if "-i" is specified, we print # a banner and run $PYTHONSTARTUP. print_banner() @@ -395,7 +450,7 @@ exec co_python_startup in mainmodule.__dict__ run_toplevel(run_it) # Then we need a prompt. - go_interactive = True + interactive = True else: # If not interactive, just read and execute stdin normally. def run_it(): Modified: pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py Thu Jun 3 22:37:55 2010 @@ -350,6 +350,32 @@ assert ('>>> ' in data) == expect_prompt # no prompt unless expected return data + def test_sysflags(self): + flags = ( + ("debug", "-d", "1"), + ("py3k_warning", "-3", "1"), + ("division_warning", "-Qwarn", "1"), + ("division_warning", "-Qwarnall", "2"), + ("division_new", "-Qnew", "1"), + ("inspect", "-i", "1"), + ("interactive", "-i", "1"), + ("optimize", "-O", "1"), + ("optimize", "-OO", "2"), + ("dont_write_bytecode", "-B", "1"), + ("no_user_site", "-s", "1"), + ("no_site", "-S", "1"), + ("ignore_environment", "-E", "1"), + ("tabcheck", "-t", "1"), + ("tabcheck", "-tt", "2"), + ("verbose", "-v", "1"), + ("unicode", "-U", "1"), + ("bytes_warning", "-b", "1"), + ) + for flag, opt, value in flags: + cmd = "%s --print-sys-flags -c 'import sys; print sys.flags'" + data = self.run(cmd % (opt,), expect_prompt=opt == "-i") + assert "%s=%s" % (flag, value) in data + def test_script_on_stdin(self): for extraargs, expected_argv in [ ('', ['']), From benjamin at codespeak.net Thu Jun 3 22:46:52 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 22:46:52 +0200 (CEST) Subject: [pypy-svn] r75080 - pypy/branch/fast-forward/pypy/module/exceptions Message-ID: <20100603204652.441D8282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 22:46:50 2010 New Revision: 75080 Modified: pypy/branch/fast-forward/pypy/module/exceptions/__init__.py pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Log: add BytesWarning Modified: pypy/branch/fast-forward/pypy/module/exceptions/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/__init__.py Thu Jun 3 22:46:50 2010 @@ -9,6 +9,7 @@ 'AssertionError' : 'interp_exceptions.W_AssertionError', 'AttributeError' : 'interp_exceptions.W_AttributeError', 'BaseException' : 'interp_exceptions.W_BaseException', + 'BytesWarning' : 'interp_exceptions.W_BytesWarning', 'DeprecationWarning' : 'interp_exceptions.W_DeprecationWarning', 'EOFError' : 'interp_exceptions.W_EOFError', 'EnvironmentError' : 'interp_exceptions.W_EnvironmentError', Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Thu Jun 3 22:46:50 2010 @@ -60,6 +60,7 @@ | | +-- UnicodeEncodeError | | +-- UnicodeTranslateError +-- Warning + +-- BytesWarning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning @@ -423,6 +424,9 @@ winerror = readwrite_attrproperty_w('w_winerror', W_WindowsError), ) +W_BytesWarning = _new_exception('BytesWarning', W_Warning, + """Mixing bytes and unicode""") + W_DeprecationWarning = _new_exception('DeprecationWarning', W_Warning, """Base class for warnings about deprecated features.""") From benjamin at codespeak.net Thu Jun 3 23:02:34 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 23:02:34 +0200 (CEST) Subject: [pypy-svn] r75081 - in pypy/branch/fast-forward/pypy: module/sys module/sys/test translator/goal Message-ID: <20100603210234.F2842282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 23:02:32 2010 New Revision: 75081 Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py pypy/branch/fast-forward/pypy/module/sys/app.py pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py pypy/branch/fast-forward/pypy/translator/goal/app_main.py Log: when translated, set sys.flags in app_main Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Thu Jun 3 23:02:32 2010 @@ -33,9 +33,9 @@ # to the trunk of a checkout or to the dir /usr/share/pypy-1.1 . 'path' : 'state.get(space).w_path', - 'py3kwarning' : 'space.w_False', # for now 'modules' : 'state.get(space).w_modules', - 'argv' : 'state.get(space).w_argv', + 'argv' : 'state.get(space).w_argv', + 'py3kwarning' : 'space.w_False', 'warnoptions' : 'state.get(space).w_warnoptions', 'builtin_module_names' : 'state.w_None', 'pypy_getudir' : 'state.pypy_getudir', @@ -84,7 +84,8 @@ 'exit' : 'app.exit', 'exitfunc' : 'app.exitfunc', 'callstats' : 'app.callstats', - 'copyright' : 'app.copyright_str', + 'copyright' : 'app.copyright_str', + 'flags' : 'app.null_sysflags', } def setbuiltinmodule(self, w_module, name): Modified: pypy/branch/fast-forward/pypy/module/sys/app.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/app.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/app.py Thu Jun 3 23:02:32 2010 @@ -3,7 +3,7 @@ The 'sys' module. """ -import sys +from pypy.lib._structseq import structseqtype, structseqfield def excepthook(exctype, value, traceback): """Handle an exception by displaying it with a traceback on sys.stderr.""" @@ -47,3 +47,26 @@ Portions Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. All Rights Reserved. """ + + +# This is tested in test_app_main.py +class sysflags: + __metaclass__ = structseqtype + + debug = structseqfield(0) + py3k_warning = structseqfield(1) + division_warning = structseqfield(2) + division_new = structseqfield(3) + inspect = structseqfield(4) + interactive = structseqfield(5) + optimize = structseqfield(6) + dont_write_bytecode = structseqfield(7) + no_user_site = structseqfield(8) + no_site = structseqfield(9) + ignore_environment = structseqfield(10) + tabcheck = structseqfield(11) + verbose = structseqfield(12) + unicode = structseqfield(13) + bytes_warning = structseqfield(14) + +null_sysflags = sysflags((0,)*15) Modified: pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Thu Jun 3 23:02:32 2010 @@ -27,10 +27,6 @@ cls.w_appdirect = cls.space.wrap(option.runappdirect) cls.w_filesystemenc = cls.space.wrap(sys.getfilesystemencoding()) - def test_sys_py3kwarning(self): - import sys - assert not sys.py3kwarning - def test_sys_in_modules(self): import sys modules = sys.modules Modified: pypy/branch/fast-forward/pypy/translator/goal/app_main.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/app_main.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/app_main.py Thu Jun 3 23:02:32 2010 @@ -235,22 +235,29 @@ _seen[dir] = True return executable - -default_options = dict.fromkeys(( +# Order is significant! +sys_flags = ( "debug", "py3k_warning", + "division_warning", + "division_new", "inspect", "interactive", "optimize", + "dont_write_bytecode", "no_user_site", - "ignore_environment", "no_site", + "ignore_environment", "tabcheck", "verbose", "unicode", "bytes_warning", - "dont_write_bytecode", - "run_command", +) + + +default_options = dict.fromkeys( + sys_flags + + ("run_command", "run_module", "run_stdin", "warnoptions", @@ -354,6 +361,10 @@ if isinstance(value, int)] "(%s)" % (", ".join(flag_opts),) print flag_opts + if we_are_translated(): + flags = [options[flag] for flag in sys_flags] + sys.flags = type(sys.flags)(flags) + sys.py3kwarning = sys.flags.py3k_warning return options def run_command_line(interactive, From benjamin at codespeak.net Thu Jun 3 23:17:22 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 23:17:22 +0200 (CEST) Subject: [pypy-svn] r75082 - in pypy/branch/fast-forward/pypy/lib: . app_test Message-ID: <20100603211722.F3DBC282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 23:17:21 2010 New Revision: 75082 Modified: pypy/branch/fast-forward/pypy/lib/_structseq.py pypy/branch/fast-forward/pypy/lib/app_test/test_structseq.py Log: give structseq a proper repr Modified: pypy/branch/fast-forward/pypy/lib/_structseq.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/_structseq.py (original) +++ pypy/branch/fast-forward/pypy/lib/_structseq.py Thu Jun 3 23:17:21 2010 @@ -61,6 +61,8 @@ dict['__new__'] = structseq_new dict['__reduce__'] = structseq_reduce dict['__setattr__'] = structseq_setattr + dict['__repr__'] = structseq_repr + dict['_name'] = dict.get('name', '') return type.__new__(metacls, classname, (tuple,), dict) @@ -105,3 +107,12 @@ def structseq_setattr(self, attr, value): raise AttributeError("%r object has no attribute %r" % ( self.__class__.__name__, attr)) + +def structseq_repr(self): + fields = {} + for field in type(self).__dict__.values(): + if isinstance(field, structseqfield): + fields[field._index] = field + parts = ["%s=%r" % (fields[index].__name__, value) + for index, value in enumerate(self)] + return "%s(%s)" % (self._name, ", ".join(parts)) Modified: pypy/branch/fast-forward/pypy/lib/app_test/test_structseq.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/app_test/test_structseq.py (original) +++ pypy/branch/fast-forward/pypy/lib/app_test/test_structseq.py Thu Jun 3 23:17:21 2010 @@ -5,6 +5,8 @@ class mydata: __metaclass__ = structseqtype + name = "mydata" + st_mode = structseqfield(0, "protection bits") st_ino = structseqfield(1) st_dev = structseqfield(2) @@ -77,3 +79,9 @@ def test_no_extra_assignments(): x = mydata(range(100, 113)) py.test.raises((TypeError, AttributeError), "x.some_random_attribute = 1") + +def test_repr(): + x = mydata(range(100, 113)) + r = repr(x) + assert r.startswith("mydata(st_mode=100, ") + assert r.endswith(")") From benjamin at codespeak.net Thu Jun 3 23:19:55 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 23:19:55 +0200 (CEST) Subject: [pypy-svn] r75083 - in pypy/branch/fast-forward/pypy/module: posix sys Message-ID: <20100603211955.B1ECA282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 23:19:54 2010 New Revision: 75083 Modified: pypy/branch/fast-forward/pypy/module/posix/app_posix.py pypy/branch/fast-forward/pypy/module/sys/app.py Log: give structseqs names Modified: pypy/branch/fast-forward/pypy/module/posix/app_posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/app_posix.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/app_posix.py Thu Jun 3 23:19:54 2010 @@ -19,6 +19,8 @@ class stat_result: __metaclass__ = structseqtype + name = "posix.stat_result" + st_mode = structseqfield(0, "protection bits") st_ino = structseqfield(1, "inode") st_dev = structseqfield(2, "device") Modified: pypy/branch/fast-forward/pypy/module/sys/app.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/app.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/app.py Thu Jun 3 23:19:54 2010 @@ -53,6 +53,8 @@ class sysflags: __metaclass__ = structseqtype + name = "sys.flags" + debug = structseqfield(0) py3k_warning = structseqfield(1) division_warning = structseqfield(2) From benjamin at codespeak.net Thu Jun 3 23:39:26 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 23:39:26 +0200 (CEST) Subject: [pypy-svn] r75084 - pypy/branch/fast-forward/pypy/tool/pytest Message-ID: <20100603213926.ACA99282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 23:39:24 2010 New Revision: 75084 Modified: pypy/branch/fast-forward/pypy/tool/pytest/confpath.py Log: configure paths with cpython version Modified: pypy/branch/fast-forward/pypy/tool/pytest/confpath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/confpath.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/confpath.py Thu Jun 3 23:39:24 2010 @@ -1,11 +1,12 @@ import autopath import py import pypy +from pypy.module.sys.version import CPYTHON_VERSION_DIR pypydir = py.path.local(pypy.__file__).dirpath() distdir = pypydir.dirpath() testresultdir = distdir.join('testresult') assert pypydir.check(dir=1) libpythondir = distdir.join('lib-python') -regrtestdir = libpythondir.join('2.5.2', 'test') -modregrtestdir = libpythondir.join('modified-2.5.2', 'test') +regrtestdir = libpythondir.join(CPYTHON_VERSION_DIR, 'test') +modregrtestdir = libpythondir.join('modified-' + CPYTHON_VERSION_DIR, 'test') From benjamin at codespeak.net Thu Jun 3 23:40:49 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 3 Jun 2010 23:40:49 +0200 (CEST) Subject: [pypy-svn] r75085 - pypy/branch/fast-forward/lib-python Message-ID: <20100603214049.413BF282BD6@codespeak.net> Author: benjamin Date: Thu Jun 3 23:40:47 2010 New Revision: 75085 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: remove killed tests Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Thu Jun 3 23:40:47 2010 @@ -259,7 +259,6 @@ RegrTest('test_hashlib.py', core=True), RegrTest('test_heapq.py', core=True), - RegrTest('test_hexoct.py', core=True), RegrTest('test_hmac.py'), RegrTest('test_hotshot.py', skip="unsupported extension module"), @@ -287,7 +286,6 @@ RegrTest('test_long.py', core=True), RegrTest('test_long_future.py', core=True), RegrTest('test_longexp.py', core=True), - RegrTest('test_macfs.py', skip=True), RegrTest('test_macostools.py', skip=True), RegrTest('test_macpath.py'), RegrTest('test_mailbox.py'), @@ -312,7 +310,6 @@ RegrTest('test_ntpath.py'), RegrTest('test_opcodes.py', core=True), RegrTest('test_openpty.py'), - RegrTest('test_operations.py', core=True), RegrTest('test_operator.py', core=True), RegrTest('test_optparse.py'), @@ -352,7 +349,6 @@ RegrTest('test_repr.py', core=True), RegrTest('test_resource.py', skip=skip_win32), RegrTest('test_rfc822.py'), - RegrTest('test_rgbimg.py', skip="unsupported extension module"), RegrTest('test_richcmp.py', core=True), RegrTest('test_robotparser.py'), @@ -372,7 +368,6 @@ RegrTest('test_slice.py', core=True), RegrTest('test_socket.py', usemodules='thread _weakref'), - RegrTest('test_socket_ssl.py', usemodules='_ssl'), RegrTest('test_socketserver.py', usemodules='thread'), RegrTest('test_softspace.py', core=True), @@ -458,7 +453,6 @@ RegrTest('test_bigaddrspace.py'), RegrTest('test_bigmem.py'), - RegrTest('test_cProfile.py'), RegrTest('test_cmd_line.py'), RegrTest('test_code.py'), RegrTest('test_coding.py'), From benjamin at codespeak.net Fri Jun 4 00:44:29 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 00:44:29 +0200 (CEST) Subject: [pypy-svn] r75086 - in pypy/branch/fast-forward: lib-python lib-python/modified-2.7.0 pypy/module/sys pypy/tool pypy/tool/pytest/run-script Message-ID: <20100603224429.847B7282BD6@codespeak.net> Author: benjamin Date: Fri Jun 4 00:44:27 2010 New Revision: 75086 Added: pypy/branch/fast-forward/lib-python/modified-2.7.0/ Modified: pypy/branch/fast-forward/lib-python/conftest.py pypy/branch/fast-forward/pypy/module/sys/state.py pypy/branch/fast-forward/pypy/tool/alarm.py pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Log: add modified dir for 2.7 Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Fri Jun 4 00:44:27 2010 @@ -127,13 +127,19 @@ RegrTest('test___all__.py', core=True), RegrTest('test___future__.py', core=True), RegrTest('test__locale.py', skip=skip_win32), + RegrTest('test_abc.py'), + RegrTest('test_abstract_numbers.py'), RegrTest('test_aepack.py', skip=True), + RegrTest('test_aifc.py'), + RegrTest('test_argparse.py'), RegrTest('test_al.py', skip=True), RegrTest('test_ast.py', core=True), RegrTest('test_anydbm.py'), RegrTest('test_applesingle.py', skip=True), RegrTest('test_array.py', core=True, usemodules='struct'), + RegrTest('test_ascii_formatd.py'), RegrTest('test_asynchat.py', usemodules='thread'), + RegrTest('test_asyncore.py'), RegrTest('test_atexit.py', core=True), RegrTest('test_audioop.py', skip=True), RegrTest('test_augassign.py', core=True), @@ -149,8 +155,10 @@ RegrTest('test_bsddb.py', skip="unsupported extension module"), RegrTest('test_bsddb185.py', skip="unsupported extension module"), RegrTest('test_bsddb3.py', skip="unsupported extension module"), + RegrTest('test_buffer.py'), RegrTest('test_bufio.py', core=True), RegrTest('test_builtin.py', core=True), + RegrTest('test_bytes.py'), RegrTest('test_bz2.py', usemodules='bz2'), RegrTest('test_calendar.py'), RegrTest('test_call.py', core=True), @@ -163,6 +171,8 @@ RegrTest('test_cl.py', skip=True), RegrTest('test_class.py', core=True), RegrTest('test_cmath.py', core=True), + RegrTest('test_cmd.py'), + RegrTest('test_cmd_line_script.py'), RegrTest('test_codeccallbacks.py', core=True), RegrTest('test_codecencodings_cn.py', skip="encodings not available"), RegrTest('test_codecencodings_hk.py', skip="encodings not available"), @@ -178,11 +188,12 @@ RegrTest('test_codecs.py', core=True), RegrTest('test_codeop.py', core=True), RegrTest('test_coercion.py', core=True), - + RegrTest('test_collections.py'), RegrTest('test_colorsys.py'), RegrTest('test_commands.py'), RegrTest('test_compare.py', core=True), RegrTest('test_compile.py', core=True), + RegrTest('test_compileall.py'), RegrTest('test_compiler.py', core=False, skip="slowly deprecating compiler"), RegrTest('test_complex.py', core=True), @@ -192,6 +203,7 @@ RegrTest('test_copy.py', core=True), RegrTest('test_copy_reg.py', core=True), RegrTest('test_cpickle.py', core=True), + RegrTest('test_cprofile.py'), RegrTest('test_crypt.py', usemodules='crypt', skip=skip_win32), RegrTest('test_csv.py'), @@ -204,7 +216,8 @@ RegrTest('test_descr.py', core=True, usemodules='_weakref'), RegrTest('test_descrtut.py', core=True), RegrTest('test_dict.py', core=True), - + RegrTest('test_dictcomps.py', core=True), + RegrTest('test_dictviews.py', core=True), RegrTest('test_difflib.py'), RegrTest('test_dircache.py', core=True), RegrTest('test_dis.py'), @@ -212,6 +225,7 @@ RegrTest('test_dl.py', skip=True), RegrTest('test_doctest.py', usemodules="thread"), RegrTest('test_doctest2.py'), + RegrTest('test_docxmlrpc.py'), RegrTest('test_dumbdbm.py'), RegrTest('test_dummy_thread.py', core=True), RegrTest('test_dummy_threading.py', core=True), @@ -220,27 +234,36 @@ RegrTest('test_email_codecs.py'), RegrTest('test_enumerate.py', core=True), RegrTest('test_eof.py', core=True), - + RegrTest('test_epoll.py'), RegrTest('test_errno.py'), RegrTest('test_exceptions.py', core=True), RegrTest('test_extcall.py', core=True), RegrTest('test_fcntl.py', usemodules='fcntl', skip=skip_win32), RegrTest('test_file.py', usemodules="posix", core=True), + RegrTest('test_file2k.py', usemodules="posix", core=True), RegrTest('test_filecmp.py', core=True), RegrTest('test_fileinput.py', core=True), + RegrTest('test_fileio.py'), RegrTest('test_fnmatch.py', core=True), RegrTest('test_fork1.py', usemodules="thread"), RegrTest('test_format.py', core=True), RegrTest('test_fpformat.py', core=True), + RegrTest('test_fractions.py'), RegrTest('test_frozen.py', skip="unsupported extension module"), + RegrTest('test_ftplib.py'), RegrTest('test_funcattrs.py', core=True), RegrTest('test_future.py', core=True), RegrTest('test_future1.py', core=True), RegrTest('test_future2.py', core=True), RegrTest('test_future3.py', core=True), + RegrTest('test_future4.py', core=True), + RegrTest('test_future5.py', core=True), + RegrTest('test_future_builtins.py'), RegrTest('test_gc.py', usemodules='_weakref', skip="implementation detail"), + RegrTest('test_gdb.py', skip="not applicable"), RegrTest('test_gdbm.py', skip="unsupported extension module"), RegrTest('test_generators.py', core=True, usemodules='thread _weakref'), + RegrTest('test_genericpath.py'), RegrTest('test_genexps.py', core=True, usemodules='_weakref'), RegrTest('test_getargs.py', skip="unsupported extension module"), RegrTest('test_getargs2.py', skip="unsupported extension module"), @@ -265,20 +288,28 @@ RegrTest('test_htmllib.py'), RegrTest('test_htmlparser.py'), RegrTest('test_httplib.py'), + RegrTest('test_httpservers.py'), RegrTest('test_imageop.py', skip="unsupported extension module"), RegrTest('test_imaplib.py'), RegrTest('test_imgfile.py', skip="unsupported extension module"), RegrTest('test_imp.py', core=True, usemodules='thread'), RegrTest('test_import.py', core=True), RegrTest('test_importhooks.py', core=True), + RegrTest('test_importlib.py'), RegrTest('test_inspect.py'), + RegrTest('test_int.py'), + RegrTest('test_int_literal.py'), + RegrTest('test_io.py'), RegrTest('test_ioctl.py'), RegrTest('test_isinstance.py', core=True), RegrTest('test_iter.py', core=True), RegrTest('test_iterlen.py', skip="undocumented internal API behavior __length_hint__"), RegrTest('test_itertools.py', core=True), - + RegrTest('test_json.py'), + RegrTest('test_kqueue.py'), RegrTest('test_largefile.py'), + RegrTest('test_lib2to3.py'), + RegrTest('test_linecache.py'), RegrTest('test_linuxaudiodev.py', skip="unsupported extension module"), RegrTest('test_list.py', core=True), RegrTest('test_locale.py', usemodules="_locale"), @@ -286,11 +317,14 @@ RegrTest('test_long.py', core=True), RegrTest('test_long_future.py', core=True), RegrTest('test_longexp.py', core=True), + RegrTest('test_macos.py'), RegrTest('test_macostools.py', skip=True), RegrTest('test_macpath.py'), RegrTest('test_mailbox.py'), RegrTest('test_marshal.py', core=True), RegrTest('test_math.py', core=True, usemodules='math'), + RegrTest('test_memoryio.py'), + RegrTest('test_memoryview.py'), RegrTest('test_md5.py'), RegrTest('test_mhlib.py'), RegrTest('test_mimetools.py'), @@ -299,10 +333,13 @@ RegrTest('test_minidom.py'), RegrTest('test_mmap.py'), RegrTest('test_module.py', core=True), + RegrTest('test_modulefinder.py'), RegrTest('test_multibytecodec.py', skip="unsupported codecs"), RegrTest('test_multibytecodec_support.py', skip="not a test"), RegrTest('test_multifile.py'), + RegrTest('test_multiprocessing.py'), RegrTest('test_mutants.py', core="possibly"), + RegrTest('test_mutex.py'), RegrTest('test_netrc.py'), RegrTest('test_new.py', core=True), RegrTest('test_nis.py', skip="unsupported extension module"), @@ -316,7 +353,7 @@ RegrTest('test_os.py', core=True), RegrTest('test_ossaudiodev.py', skip="unsupported extension module"), RegrTest('test_parser.py', skip="slowly deprecating compiler"), - + RegrTest('test_pdb.py'), RegrTest('test_peepholer.py'), RegrTest('test_pep247.py'), RegrTest('test_pep263.py'), @@ -324,28 +361,35 @@ RegrTest('test_pep292.py'), RegrTest('test_pickle.py', core=True), RegrTest('test_pickletools.py', core=False), + RegrTest('test_pipes.py'), RegrTest('test_pkg.py', core=True), RegrTest('test_pkgimport.py', core=True), + RegrTest('test_pkgutil.py'), RegrTest('test_plistlib.py', skip="unsupported module"), RegrTest('test_poll.py', skip=skip_win32), RegrTest('test_popen.py'), RegrTest('test_popen2.py'), + RegrTest('test_poplib.py'), RegrTest('test_posix.py'), RegrTest('test_posixpath.py'), RegrTest('test_pow.py', core=True), RegrTest('test_pprint.py', core=True), + RegrTest('test_print.py', core=True), RegrTest('test_profile.py'), RegrTest('test_profilehooks.py', core=True), + RegrTest('test_property.py', core=True), + RegrTest('test_pstats.py'), RegrTest('test_pty.py', skip="unsupported extension module"), RegrTest('test_pwd.py', skip=skip_win32), - + RegrTest('test_py3kwarn.py'), RegrTest('test_pyclbr.py'), + RegrTest('test_pydoc.py'), RegrTest('test_pyexpat.py'), RegrTest('test_queue.py', usemodules='thread'), RegrTest('test_quopri.py'), RegrTest('test_random.py'), RegrTest('test_re.py', core=True), - + RegrTest('test_readline.py'), RegrTest('test_repr.py', core=True), RegrTest('test_resource.py', skip=skip_win32), RegrTest('test_rfc822.py'), @@ -358,20 +402,25 @@ RegrTest('test_select.py'), RegrTest('test_set.py', core=True), RegrTest('test_sets.py'), + RegrTest('test_setcomps.py', core=True), RegrTest('test_sgmllib.py'), RegrTest('test_sha.py'), RegrTest('test_shelve.py'), RegrTest('test_shlex.py'), RegrTest('test_shutil.py'), RegrTest('test_signal.py'), + RegrTest('test_SimpleHTTPServer.py'), RegrTest('test_site.py', core=False), RegrTest('test_slice.py', core=True), + RegrTest('test_smtplib.py'), + RegrTest('test_smtpnet.py'), RegrTest('test_socket.py', usemodules='thread _weakref'), RegrTest('test_socketserver.py', usemodules='thread'), RegrTest('test_softspace.py', core=True), RegrTest('test_sort.py', core=True), + RegrTest('test_ssl.py'), RegrTest('test_str.py', core=True), RegrTest('test_strftime.py'), @@ -381,7 +430,7 @@ RegrTest('test_strop.py', skip="deprecated"), RegrTest('test_strptime.py'), - + RegrTest('test_strtod.py'), RegrTest('test_struct.py', usemodules='struct'), RegrTest('test_structmembers.py', skip="CPython specific"), RegrTest('test_structseq.py'), @@ -391,9 +440,10 @@ RegrTest('test_symtable.py', skip="implementation detail"), RegrTest('test_syntax.py', core=True), RegrTest('test_sys.py', core=True), + RegrTest('test_sysconfig.py'), RegrTest('test_tcl.py', skip="unsupported extension module"), RegrTest('test_tarfile.py'), - + RegrTest('test_telnetlib.py'), RegrTest('test_tempfile.py'), RegrTest('test_textwrap.py'), @@ -408,22 +458,25 @@ RegrTest('test_time.py', core=True), RegrTest('test_timeout.py'), - + RegrTest('test_tk.py'), + RegrTest('test_ttk_guionly.py'), + RegrTest('test_ttk_textonly.py'), RegrTest('test_tokenize.py'), RegrTest('test_trace.py', core=True), RegrTest('test_traceback.py', core=True), RegrTest('test_transformer.py', core=True), RegrTest('test_tuple.py', core=True), - + RegrTest('test_typechecks.py'), RegrTest('test_types.py', core=True), - RegrTest('test_ucn.py'), RegrTest('test_unary.py', core=True), + RegrTest('test_undocumented_details.py'), RegrTest('test_unicode.py', core=True), RegrTest('test_unicode_file.py'), RegrTest('test_unicodedata.py'), RegrTest('test_unittest.py', core=True), - RegrTest('test_univnewlines.py', core=True), + RegrTest('test_univnewlines.py'), + RegrTest('test_univnewlines2k.py', core=True), RegrTest('test_unpack.py', core=True), RegrTest('test_urllib.py'), RegrTest('test_urllib2.py'), @@ -438,6 +491,7 @@ RegrTest('test_warnings.py', core=True), RegrTest('test_wave.py', skip="unsupported extension module"), RegrTest('test_weakref.py', core=True, usemodules='_weakref'), + RegrTest('test_weakset.py'), RegrTest('test_whichdb.py'), RegrTest('test_winreg.py', skip=only_win32), @@ -449,6 +503,7 @@ RegrTest('test_xrange.py', core=True), RegrTest('test_zipfile.py'), RegrTest('test_zipimport.py', usemodules='zlib zipimport'), + RegrTest('test_zipimport_support.py', usemodules='zlib zipimport'), RegrTest('test_zlib.py', usemodules='zlib'), RegrTest('test_bigaddrspace.py'), @@ -609,7 +664,6 @@ pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) sopt = " ".join(pypy_options) - cmd = "%s %s %d %s %s %s %s %s" %( python, alarm_script, TIMEOUT, pypy_script, sopt, Modified: pypy/branch/fast-forward/pypy/module/sys/state.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/state.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/state.py Fri Jun 4 00:44:27 2010 @@ -42,21 +42,14 @@ python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) - have_modified = True - try: - checkdir(python_std_lib_modified) - except OSError, e: - if e.errno != errno.ENOENT: - raise - have_modified = False + checkdir(python_std_lib_modified) pypydir = os.path.join(srcdir, 'pypy') pypy_lib = os.path.join(pypydir, 'lib') checkdir(pypy_lib) importlist = [] importlist.append(pypy_lib) - if have_modified: - importlist.append(python_std_lib_modified) + importlist.append(python_std_lib_modified) importlist.append(python_std_lib) return importlist Modified: pypy/branch/fast-forward/pypy/tool/alarm.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/alarm.py (original) +++ pypy/branch/fast-forward/pypy/tool/alarm.py Fri Jun 4 00:44:27 2010 @@ -14,7 +14,6 @@ import time import thread - def timeout_thread(timeout, finished): stderr = sys.stderr interrupt_main = thread.interrupt_main Modified: pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Fri Jun 4 00:44:27 2010 @@ -4,7 +4,7 @@ test_support.verbose = int(sys.argv[1]) sys.argv[:] = sys.argv[2:] -modname = sys.argv[0] +modname = sys.argv[0] impname = 'test.' + modname try: mod = __import__(impname, globals(), locals(), [modname]) From benjamin at codespeak.net Fri Jun 4 00:49:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 00:49:09 +0200 (CEST) Subject: [pypy-svn] r75087 - in pypy/branch/fast-forward: lib-python pypy/tool pypy/tool/pytest/run-script Message-ID: <20100603224909.7A150282BD6@codespeak.net> Author: benjamin Date: Fri Jun 4 00:49:07 2010 New Revision: 75087 Modified: pypy/branch/fast-forward/lib-python/conftest.py pypy/branch/fast-forward/pypy/tool/alarm.py pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Log: revert random changes Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Fri Jun 4 00:49:07 2010 @@ -127,19 +127,13 @@ RegrTest('test___all__.py', core=True), RegrTest('test___future__.py', core=True), RegrTest('test__locale.py', skip=skip_win32), - RegrTest('test_abc.py'), - RegrTest('test_abstract_numbers.py'), RegrTest('test_aepack.py', skip=True), - RegrTest('test_aifc.py'), - RegrTest('test_argparse.py'), RegrTest('test_al.py', skip=True), RegrTest('test_ast.py', core=True), RegrTest('test_anydbm.py'), RegrTest('test_applesingle.py', skip=True), RegrTest('test_array.py', core=True, usemodules='struct'), - RegrTest('test_ascii_formatd.py'), RegrTest('test_asynchat.py', usemodules='thread'), - RegrTest('test_asyncore.py'), RegrTest('test_atexit.py', core=True), RegrTest('test_audioop.py', skip=True), RegrTest('test_augassign.py', core=True), @@ -155,10 +149,8 @@ RegrTest('test_bsddb.py', skip="unsupported extension module"), RegrTest('test_bsddb185.py', skip="unsupported extension module"), RegrTest('test_bsddb3.py', skip="unsupported extension module"), - RegrTest('test_buffer.py'), RegrTest('test_bufio.py', core=True), RegrTest('test_builtin.py', core=True), - RegrTest('test_bytes.py'), RegrTest('test_bz2.py', usemodules='bz2'), RegrTest('test_calendar.py'), RegrTest('test_call.py', core=True), @@ -171,8 +163,6 @@ RegrTest('test_cl.py', skip=True), RegrTest('test_class.py', core=True), RegrTest('test_cmath.py', core=True), - RegrTest('test_cmd.py'), - RegrTest('test_cmd_line_script.py'), RegrTest('test_codeccallbacks.py', core=True), RegrTest('test_codecencodings_cn.py', skip="encodings not available"), RegrTest('test_codecencodings_hk.py', skip="encodings not available"), @@ -188,12 +178,11 @@ RegrTest('test_codecs.py', core=True), RegrTest('test_codeop.py', core=True), RegrTest('test_coercion.py', core=True), - RegrTest('test_collections.py'), + RegrTest('test_colorsys.py'), RegrTest('test_commands.py'), RegrTest('test_compare.py', core=True), RegrTest('test_compile.py', core=True), - RegrTest('test_compileall.py'), RegrTest('test_compiler.py', core=False, skip="slowly deprecating compiler"), RegrTest('test_complex.py', core=True), @@ -203,7 +192,6 @@ RegrTest('test_copy.py', core=True), RegrTest('test_copy_reg.py', core=True), RegrTest('test_cpickle.py', core=True), - RegrTest('test_cprofile.py'), RegrTest('test_crypt.py', usemodules='crypt', skip=skip_win32), RegrTest('test_csv.py'), @@ -216,8 +204,7 @@ RegrTest('test_descr.py', core=True, usemodules='_weakref'), RegrTest('test_descrtut.py', core=True), RegrTest('test_dict.py', core=True), - RegrTest('test_dictcomps.py', core=True), - RegrTest('test_dictviews.py', core=True), + RegrTest('test_difflib.py'), RegrTest('test_dircache.py', core=True), RegrTest('test_dis.py'), @@ -225,7 +212,6 @@ RegrTest('test_dl.py', skip=True), RegrTest('test_doctest.py', usemodules="thread"), RegrTest('test_doctest2.py'), - RegrTest('test_docxmlrpc.py'), RegrTest('test_dumbdbm.py'), RegrTest('test_dummy_thread.py', core=True), RegrTest('test_dummy_threading.py', core=True), @@ -234,36 +220,27 @@ RegrTest('test_email_codecs.py'), RegrTest('test_enumerate.py', core=True), RegrTest('test_eof.py', core=True), - RegrTest('test_epoll.py'), + RegrTest('test_errno.py'), RegrTest('test_exceptions.py', core=True), RegrTest('test_extcall.py', core=True), RegrTest('test_fcntl.py', usemodules='fcntl', skip=skip_win32), RegrTest('test_file.py', usemodules="posix", core=True), - RegrTest('test_file2k.py', usemodules="posix", core=True), RegrTest('test_filecmp.py', core=True), RegrTest('test_fileinput.py', core=True), - RegrTest('test_fileio.py'), RegrTest('test_fnmatch.py', core=True), RegrTest('test_fork1.py', usemodules="thread"), RegrTest('test_format.py', core=True), RegrTest('test_fpformat.py', core=True), - RegrTest('test_fractions.py'), RegrTest('test_frozen.py', skip="unsupported extension module"), - RegrTest('test_ftplib.py'), RegrTest('test_funcattrs.py', core=True), RegrTest('test_future.py', core=True), RegrTest('test_future1.py', core=True), RegrTest('test_future2.py', core=True), RegrTest('test_future3.py', core=True), - RegrTest('test_future4.py', core=True), - RegrTest('test_future5.py', core=True), - RegrTest('test_future_builtins.py'), RegrTest('test_gc.py', usemodules='_weakref', skip="implementation detail"), - RegrTest('test_gdb.py', skip="not applicable"), RegrTest('test_gdbm.py', skip="unsupported extension module"), RegrTest('test_generators.py', core=True, usemodules='thread _weakref'), - RegrTest('test_genericpath.py'), RegrTest('test_genexps.py', core=True, usemodules='_weakref'), RegrTest('test_getargs.py', skip="unsupported extension module"), RegrTest('test_getargs2.py', skip="unsupported extension module"), @@ -288,28 +265,20 @@ RegrTest('test_htmllib.py'), RegrTest('test_htmlparser.py'), RegrTest('test_httplib.py'), - RegrTest('test_httpservers.py'), RegrTest('test_imageop.py', skip="unsupported extension module"), RegrTest('test_imaplib.py'), RegrTest('test_imgfile.py', skip="unsupported extension module"), RegrTest('test_imp.py', core=True, usemodules='thread'), RegrTest('test_import.py', core=True), RegrTest('test_importhooks.py', core=True), - RegrTest('test_importlib.py'), RegrTest('test_inspect.py'), - RegrTest('test_int.py'), - RegrTest('test_int_literal.py'), - RegrTest('test_io.py'), RegrTest('test_ioctl.py'), RegrTest('test_isinstance.py', core=True), RegrTest('test_iter.py', core=True), RegrTest('test_iterlen.py', skip="undocumented internal API behavior __length_hint__"), RegrTest('test_itertools.py', core=True), - RegrTest('test_json.py'), - RegrTest('test_kqueue.py'), + RegrTest('test_largefile.py'), - RegrTest('test_lib2to3.py'), - RegrTest('test_linecache.py'), RegrTest('test_linuxaudiodev.py', skip="unsupported extension module"), RegrTest('test_list.py', core=True), RegrTest('test_locale.py', usemodules="_locale"), @@ -317,14 +286,11 @@ RegrTest('test_long.py', core=True), RegrTest('test_long_future.py', core=True), RegrTest('test_longexp.py', core=True), - RegrTest('test_macos.py'), RegrTest('test_macostools.py', skip=True), RegrTest('test_macpath.py'), RegrTest('test_mailbox.py'), RegrTest('test_marshal.py', core=True), RegrTest('test_math.py', core=True, usemodules='math'), - RegrTest('test_memoryio.py'), - RegrTest('test_memoryview.py'), RegrTest('test_md5.py'), RegrTest('test_mhlib.py'), RegrTest('test_mimetools.py'), @@ -333,13 +299,10 @@ RegrTest('test_minidom.py'), RegrTest('test_mmap.py'), RegrTest('test_module.py', core=True), - RegrTest('test_modulefinder.py'), RegrTest('test_multibytecodec.py', skip="unsupported codecs"), RegrTest('test_multibytecodec_support.py', skip="not a test"), RegrTest('test_multifile.py'), - RegrTest('test_multiprocessing.py'), RegrTest('test_mutants.py', core="possibly"), - RegrTest('test_mutex.py'), RegrTest('test_netrc.py'), RegrTest('test_new.py', core=True), RegrTest('test_nis.py', skip="unsupported extension module"), @@ -353,7 +316,7 @@ RegrTest('test_os.py', core=True), RegrTest('test_ossaudiodev.py', skip="unsupported extension module"), RegrTest('test_parser.py', skip="slowly deprecating compiler"), - RegrTest('test_pdb.py'), + RegrTest('test_peepholer.py'), RegrTest('test_pep247.py'), RegrTest('test_pep263.py'), @@ -361,35 +324,28 @@ RegrTest('test_pep292.py'), RegrTest('test_pickle.py', core=True), RegrTest('test_pickletools.py', core=False), - RegrTest('test_pipes.py'), RegrTest('test_pkg.py', core=True), RegrTest('test_pkgimport.py', core=True), - RegrTest('test_pkgutil.py'), RegrTest('test_plistlib.py', skip="unsupported module"), RegrTest('test_poll.py', skip=skip_win32), RegrTest('test_popen.py'), RegrTest('test_popen2.py'), - RegrTest('test_poplib.py'), RegrTest('test_posix.py'), RegrTest('test_posixpath.py'), RegrTest('test_pow.py', core=True), RegrTest('test_pprint.py', core=True), - RegrTest('test_print.py', core=True), RegrTest('test_profile.py'), RegrTest('test_profilehooks.py', core=True), - RegrTest('test_property.py', core=True), - RegrTest('test_pstats.py'), RegrTest('test_pty.py', skip="unsupported extension module"), RegrTest('test_pwd.py', skip=skip_win32), - RegrTest('test_py3kwarn.py'), + RegrTest('test_pyclbr.py'), - RegrTest('test_pydoc.py'), RegrTest('test_pyexpat.py'), RegrTest('test_queue.py', usemodules='thread'), RegrTest('test_quopri.py'), RegrTest('test_random.py'), RegrTest('test_re.py', core=True), - RegrTest('test_readline.py'), + RegrTest('test_repr.py', core=True), RegrTest('test_resource.py', skip=skip_win32), RegrTest('test_rfc822.py'), @@ -402,25 +358,20 @@ RegrTest('test_select.py'), RegrTest('test_set.py', core=True), RegrTest('test_sets.py'), - RegrTest('test_setcomps.py', core=True), RegrTest('test_sgmllib.py'), RegrTest('test_sha.py'), RegrTest('test_shelve.py'), RegrTest('test_shlex.py'), RegrTest('test_shutil.py'), RegrTest('test_signal.py'), - RegrTest('test_SimpleHTTPServer.py'), RegrTest('test_site.py', core=False), RegrTest('test_slice.py', core=True), - RegrTest('test_smtplib.py'), - RegrTest('test_smtpnet.py'), RegrTest('test_socket.py', usemodules='thread _weakref'), RegrTest('test_socketserver.py', usemodules='thread'), RegrTest('test_softspace.py', core=True), RegrTest('test_sort.py', core=True), - RegrTest('test_ssl.py'), RegrTest('test_str.py', core=True), RegrTest('test_strftime.py'), @@ -430,7 +381,7 @@ RegrTest('test_strop.py', skip="deprecated"), RegrTest('test_strptime.py'), - RegrTest('test_strtod.py'), + RegrTest('test_struct.py', usemodules='struct'), RegrTest('test_structmembers.py', skip="CPython specific"), RegrTest('test_structseq.py'), @@ -440,10 +391,9 @@ RegrTest('test_symtable.py', skip="implementation detail"), RegrTest('test_syntax.py', core=True), RegrTest('test_sys.py', core=True), - RegrTest('test_sysconfig.py'), RegrTest('test_tcl.py', skip="unsupported extension module"), RegrTest('test_tarfile.py'), - RegrTest('test_telnetlib.py'), + RegrTest('test_tempfile.py'), RegrTest('test_textwrap.py'), @@ -458,25 +408,22 @@ RegrTest('test_time.py', core=True), RegrTest('test_timeout.py'), - RegrTest('test_tk.py'), - RegrTest('test_ttk_guionly.py'), - RegrTest('test_ttk_textonly.py'), + RegrTest('test_tokenize.py'), RegrTest('test_trace.py', core=True), RegrTest('test_traceback.py', core=True), RegrTest('test_transformer.py', core=True), RegrTest('test_tuple.py', core=True), - RegrTest('test_typechecks.py'), + RegrTest('test_types.py', core=True), + RegrTest('test_ucn.py'), RegrTest('test_unary.py', core=True), - RegrTest('test_undocumented_details.py'), RegrTest('test_unicode.py', core=True), RegrTest('test_unicode_file.py'), RegrTest('test_unicodedata.py'), RegrTest('test_unittest.py', core=True), - RegrTest('test_univnewlines.py'), - RegrTest('test_univnewlines2k.py', core=True), + RegrTest('test_univnewlines.py', core=True), RegrTest('test_unpack.py', core=True), RegrTest('test_urllib.py'), RegrTest('test_urllib2.py'), @@ -491,7 +438,6 @@ RegrTest('test_warnings.py', core=True), RegrTest('test_wave.py', skip="unsupported extension module"), RegrTest('test_weakref.py', core=True, usemodules='_weakref'), - RegrTest('test_weakset.py'), RegrTest('test_whichdb.py'), RegrTest('test_winreg.py', skip=only_win32), @@ -503,7 +449,6 @@ RegrTest('test_xrange.py', core=True), RegrTest('test_zipfile.py'), RegrTest('test_zipimport.py', usemodules='zlib zipimport'), - RegrTest('test_zipimport_support.py', usemodules='zlib zipimport'), RegrTest('test_zlib.py', usemodules='zlib'), RegrTest('test_bigaddrspace.py'), @@ -664,6 +609,7 @@ pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) sopt = " ".join(pypy_options) + cmd = "%s %s %d %s %s %s %s %s" %( python, alarm_script, TIMEOUT, pypy_script, sopt, Modified: pypy/branch/fast-forward/pypy/tool/alarm.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/alarm.py (original) +++ pypy/branch/fast-forward/pypy/tool/alarm.py Fri Jun 4 00:49:07 2010 @@ -14,6 +14,7 @@ import time import thread + def timeout_thread(timeout, finished): stderr = sys.stderr interrupt_main = thread.interrupt_main Modified: pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Fri Jun 4 00:49:07 2010 @@ -4,7 +4,7 @@ test_support.verbose = int(sys.argv[1]) sys.argv[:] = sys.argv[2:] -modname = sys.argv[0] +modname = sys.argv[0] impname = 'test.' + modname try: mod = __import__(impname, globals(), locals(), [modname]) From benjamin at codespeak.net Fri Jun 4 00:49:46 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 00:49:46 +0200 (CEST) Subject: [pypy-svn] r75088 - pypy/branch/fast-forward/lib-python Message-ID: <20100603224946.A6440282BD6@codespeak.net> Author: benjamin Date: Fri Jun 4 00:49:44 2010 New Revision: 75088 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: add new lib-python tests to conftest.py Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Fri Jun 4 00:49:44 2010 @@ -127,13 +127,19 @@ RegrTest('test___all__.py', core=True), RegrTest('test___future__.py', core=True), RegrTest('test__locale.py', skip=skip_win32), + RegrTest('test_abc.py'), + RegrTest('test_abstract_numbers.py'), RegrTest('test_aepack.py', skip=True), + RegrTest('test_aifc.py'), + RegrTest('test_argparse.py'), RegrTest('test_al.py', skip=True), RegrTest('test_ast.py', core=True), RegrTest('test_anydbm.py'), RegrTest('test_applesingle.py', skip=True), RegrTest('test_array.py', core=True, usemodules='struct'), + RegrTest('test_ascii_formatd.py'), RegrTest('test_asynchat.py', usemodules='thread'), + RegrTest('test_asyncore.py'), RegrTest('test_atexit.py', core=True), RegrTest('test_audioop.py', skip=True), RegrTest('test_augassign.py', core=True), @@ -149,8 +155,10 @@ RegrTest('test_bsddb.py', skip="unsupported extension module"), RegrTest('test_bsddb185.py', skip="unsupported extension module"), RegrTest('test_bsddb3.py', skip="unsupported extension module"), + RegrTest('test_buffer.py'), RegrTest('test_bufio.py', core=True), RegrTest('test_builtin.py', core=True), + RegrTest('test_bytes.py'), RegrTest('test_bz2.py', usemodules='bz2'), RegrTest('test_calendar.py'), RegrTest('test_call.py', core=True), @@ -163,6 +171,8 @@ RegrTest('test_cl.py', skip=True), RegrTest('test_class.py', core=True), RegrTest('test_cmath.py', core=True), + RegrTest('test_cmd.py'), + RegrTest('test_cmd_line_script.py'), RegrTest('test_codeccallbacks.py', core=True), RegrTest('test_codecencodings_cn.py', skip="encodings not available"), RegrTest('test_codecencodings_hk.py', skip="encodings not available"), @@ -178,11 +188,12 @@ RegrTest('test_codecs.py', core=True), RegrTest('test_codeop.py', core=True), RegrTest('test_coercion.py', core=True), - + RegrTest('test_collections.py'), RegrTest('test_colorsys.py'), RegrTest('test_commands.py'), RegrTest('test_compare.py', core=True), RegrTest('test_compile.py', core=True), + RegrTest('test_compileall.py'), RegrTest('test_compiler.py', core=False, skip="slowly deprecating compiler"), RegrTest('test_complex.py', core=True), @@ -192,6 +203,7 @@ RegrTest('test_copy.py', core=True), RegrTest('test_copy_reg.py', core=True), RegrTest('test_cpickle.py', core=True), + RegrTest('test_cprofile.py'), RegrTest('test_crypt.py', usemodules='crypt', skip=skip_win32), RegrTest('test_csv.py'), @@ -204,7 +216,8 @@ RegrTest('test_descr.py', core=True, usemodules='_weakref'), RegrTest('test_descrtut.py', core=True), RegrTest('test_dict.py', core=True), - + RegrTest('test_dictcomps.py', core=True), + RegrTest('test_dictviews.py', core=True), RegrTest('test_difflib.py'), RegrTest('test_dircache.py', core=True), RegrTest('test_dis.py'), @@ -212,6 +225,7 @@ RegrTest('test_dl.py', skip=True), RegrTest('test_doctest.py', usemodules="thread"), RegrTest('test_doctest2.py'), + RegrTest('test_docxmlrpc.py'), RegrTest('test_dumbdbm.py'), RegrTest('test_dummy_thread.py', core=True), RegrTest('test_dummy_threading.py', core=True), @@ -220,27 +234,36 @@ RegrTest('test_email_codecs.py'), RegrTest('test_enumerate.py', core=True), RegrTest('test_eof.py', core=True), - + RegrTest('test_epoll.py'), RegrTest('test_errno.py'), RegrTest('test_exceptions.py', core=True), RegrTest('test_extcall.py', core=True), RegrTest('test_fcntl.py', usemodules='fcntl', skip=skip_win32), RegrTest('test_file.py', usemodules="posix", core=True), + RegrTest('test_file2k.py', usemodules="posix", core=True), RegrTest('test_filecmp.py', core=True), RegrTest('test_fileinput.py', core=True), + RegrTest('test_fileio.py'), RegrTest('test_fnmatch.py', core=True), RegrTest('test_fork1.py', usemodules="thread"), RegrTest('test_format.py', core=True), RegrTest('test_fpformat.py', core=True), + RegrTest('test_fractions.py'), RegrTest('test_frozen.py', skip="unsupported extension module"), + RegrTest('test_ftplib.py'), RegrTest('test_funcattrs.py', core=True), RegrTest('test_future.py', core=True), RegrTest('test_future1.py', core=True), RegrTest('test_future2.py', core=True), RegrTest('test_future3.py', core=True), + RegrTest('test_future4.py', core=True), + RegrTest('test_future5.py', core=True), + RegrTest('test_future_builtins.py'), RegrTest('test_gc.py', usemodules='_weakref', skip="implementation detail"), + RegrTest('test_gdb.py', skip="not applicable"), RegrTest('test_gdbm.py', skip="unsupported extension module"), RegrTest('test_generators.py', core=True, usemodules='thread _weakref'), + RegrTest('test_genericpath.py'), RegrTest('test_genexps.py', core=True, usemodules='_weakref'), RegrTest('test_getargs.py', skip="unsupported extension module"), RegrTest('test_getargs2.py', skip="unsupported extension module"), @@ -265,20 +288,28 @@ RegrTest('test_htmllib.py'), RegrTest('test_htmlparser.py'), RegrTest('test_httplib.py'), + RegrTest('test_httpservers.py'), RegrTest('test_imageop.py', skip="unsupported extension module"), RegrTest('test_imaplib.py'), RegrTest('test_imgfile.py', skip="unsupported extension module"), RegrTest('test_imp.py', core=True, usemodules='thread'), RegrTest('test_import.py', core=True), RegrTest('test_importhooks.py', core=True), + RegrTest('test_importlib.py'), RegrTest('test_inspect.py'), + RegrTest('test_int.py'), + RegrTest('test_int_literal.py'), + RegrTest('test_io.py'), RegrTest('test_ioctl.py'), RegrTest('test_isinstance.py', core=True), RegrTest('test_iter.py', core=True), RegrTest('test_iterlen.py', skip="undocumented internal API behavior __length_hint__"), RegrTest('test_itertools.py', core=True), - + RegrTest('test_json.py'), + RegrTest('test_kqueue.py'), RegrTest('test_largefile.py'), + RegrTest('test_lib2to3.py'), + RegrTest('test_linecache.py'), RegrTest('test_linuxaudiodev.py', skip="unsupported extension module"), RegrTest('test_list.py', core=True), RegrTest('test_locale.py', usemodules="_locale"), @@ -286,11 +317,14 @@ RegrTest('test_long.py', core=True), RegrTest('test_long_future.py', core=True), RegrTest('test_longexp.py', core=True), + RegrTest('test_macos.py'), RegrTest('test_macostools.py', skip=True), RegrTest('test_macpath.py'), RegrTest('test_mailbox.py'), RegrTest('test_marshal.py', core=True), RegrTest('test_math.py', core=True, usemodules='math'), + RegrTest('test_memoryio.py'), + RegrTest('test_memoryview.py'), RegrTest('test_md5.py'), RegrTest('test_mhlib.py'), RegrTest('test_mimetools.py'), @@ -299,10 +333,13 @@ RegrTest('test_minidom.py'), RegrTest('test_mmap.py'), RegrTest('test_module.py', core=True), + RegrTest('test_modulefinder.py'), RegrTest('test_multibytecodec.py', skip="unsupported codecs"), RegrTest('test_multibytecodec_support.py', skip="not a test"), RegrTest('test_multifile.py'), + RegrTest('test_multiprocessing.py'), RegrTest('test_mutants.py', core="possibly"), + RegrTest('test_mutex.py'), RegrTest('test_netrc.py'), RegrTest('test_new.py', core=True), RegrTest('test_nis.py', skip="unsupported extension module"), @@ -316,7 +353,7 @@ RegrTest('test_os.py', core=True), RegrTest('test_ossaudiodev.py', skip="unsupported extension module"), RegrTest('test_parser.py', skip="slowly deprecating compiler"), - + RegrTest('test_pdb.py'), RegrTest('test_peepholer.py'), RegrTest('test_pep247.py'), RegrTest('test_pep263.py'), @@ -324,28 +361,35 @@ RegrTest('test_pep292.py'), RegrTest('test_pickle.py', core=True), RegrTest('test_pickletools.py', core=False), + RegrTest('test_pipes.py'), RegrTest('test_pkg.py', core=True), RegrTest('test_pkgimport.py', core=True), + RegrTest('test_pkgutil.py'), RegrTest('test_plistlib.py', skip="unsupported module"), RegrTest('test_poll.py', skip=skip_win32), RegrTest('test_popen.py'), RegrTest('test_popen2.py'), + RegrTest('test_poplib.py'), RegrTest('test_posix.py'), RegrTest('test_posixpath.py'), RegrTest('test_pow.py', core=True), RegrTest('test_pprint.py', core=True), + RegrTest('test_print.py', core=True), RegrTest('test_profile.py'), RegrTest('test_profilehooks.py', core=True), + RegrTest('test_property.py', core=True), + RegrTest('test_pstats.py'), RegrTest('test_pty.py', skip="unsupported extension module"), RegrTest('test_pwd.py', skip=skip_win32), - + RegrTest('test_py3kwarn.py'), RegrTest('test_pyclbr.py'), + RegrTest('test_pydoc.py'), RegrTest('test_pyexpat.py'), RegrTest('test_queue.py', usemodules='thread'), RegrTest('test_quopri.py'), RegrTest('test_random.py'), RegrTest('test_re.py', core=True), - + RegrTest('test_readline.py'), RegrTest('test_repr.py', core=True), RegrTest('test_resource.py', skip=skip_win32), RegrTest('test_rfc822.py'), @@ -358,20 +402,25 @@ RegrTest('test_select.py'), RegrTest('test_set.py', core=True), RegrTest('test_sets.py'), + RegrTest('test_setcomps.py', core=True), RegrTest('test_sgmllib.py'), RegrTest('test_sha.py'), RegrTest('test_shelve.py'), RegrTest('test_shlex.py'), RegrTest('test_shutil.py'), RegrTest('test_signal.py'), + RegrTest('test_SimpleHTTPServer.py'), RegrTest('test_site.py', core=False), RegrTest('test_slice.py', core=True), + RegrTest('test_smtplib.py'), + RegrTest('test_smtpnet.py'), RegrTest('test_socket.py', usemodules='thread _weakref'), RegrTest('test_socketserver.py', usemodules='thread'), RegrTest('test_softspace.py', core=True), RegrTest('test_sort.py', core=True), + RegrTest('test_ssl.py'), RegrTest('test_str.py', core=True), RegrTest('test_strftime.py'), @@ -381,7 +430,7 @@ RegrTest('test_strop.py', skip="deprecated"), RegrTest('test_strptime.py'), - + RegrTest('test_strtod.py'), RegrTest('test_struct.py', usemodules='struct'), RegrTest('test_structmembers.py', skip="CPython specific"), RegrTest('test_structseq.py'), @@ -391,9 +440,10 @@ RegrTest('test_symtable.py', skip="implementation detail"), RegrTest('test_syntax.py', core=True), RegrTest('test_sys.py', core=True), + RegrTest('test_sysconfig.py'), RegrTest('test_tcl.py', skip="unsupported extension module"), RegrTest('test_tarfile.py'), - + RegrTest('test_telnetlib.py'), RegrTest('test_tempfile.py'), RegrTest('test_textwrap.py'), @@ -408,22 +458,25 @@ RegrTest('test_time.py', core=True), RegrTest('test_timeout.py'), - + RegrTest('test_tk.py'), + RegrTest('test_ttk_guionly.py'), + RegrTest('test_ttk_textonly.py'), RegrTest('test_tokenize.py'), RegrTest('test_trace.py', core=True), RegrTest('test_traceback.py', core=True), RegrTest('test_transformer.py', core=True), RegrTest('test_tuple.py', core=True), - + RegrTest('test_typechecks.py'), RegrTest('test_types.py', core=True), - RegrTest('test_ucn.py'), RegrTest('test_unary.py', core=True), + RegrTest('test_undocumented_details.py'), RegrTest('test_unicode.py', core=True), RegrTest('test_unicode_file.py'), RegrTest('test_unicodedata.py'), RegrTest('test_unittest.py', core=True), - RegrTest('test_univnewlines.py', core=True), + RegrTest('test_univnewlines.py'), + RegrTest('test_univnewlines2k.py', core=True), RegrTest('test_unpack.py', core=True), RegrTest('test_urllib.py'), RegrTest('test_urllib2.py'), @@ -438,6 +491,7 @@ RegrTest('test_warnings.py', core=True), RegrTest('test_wave.py', skip="unsupported extension module"), RegrTest('test_weakref.py', core=True, usemodules='_weakref'), + RegrTest('test_weakset.py'), RegrTest('test_whichdb.py'), RegrTest('test_winreg.py', skip=only_win32), @@ -449,6 +503,7 @@ RegrTest('test_xrange.py', core=True), RegrTest('test_zipfile.py'), RegrTest('test_zipimport.py', usemodules='zlib zipimport'), + RegrTest('test_zipimport_support.py', usemodules='zlib zipimport'), RegrTest('test_zlib.py', usemodules='zlib'), RegrTest('test_bigaddrspace.py'), @@ -609,7 +664,6 @@ pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) sopt = " ".join(pypy_options) - cmd = "%s %s %d %s %s %s %s %s" %( python, alarm_script, TIMEOUT, pypy_script, sopt, From benjamin at codespeak.net Fri Jun 4 01:02:43 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:02:43 +0200 (CEST) Subject: [pypy-svn] r75089 - in pypy/branch/fast-forward/pypy/interpreter/pyparser: . data Message-ID: <20100603230243.D93DF282BD6@codespeak.net> Author: benjamin Date: Fri Jun 4 01:02:42 2010 New Revision: 75089 Added: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py Log: add Grammar2.7 as a copy of Grammar2.5 to work off Added: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- (empty file) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Fri Jun 4 01:02:42 2010 @@ -0,0 +1,148 @@ +# Grammar for Python + +# Note: Changing the grammar specified in this file will most likely +# require corresponding changes in the parser module +# (../Modules/parsermodule.c). If you can't make the changes to +# that module yourself, please co-ordinate the required changes +# with someone who can; ask around on python-dev for help. Fred +# Drake will probably be listening there. + +# NOTE WELL: You should also follow all the steps listed in PEP 306, +# "How to Change Python's Grammar" + +# Commands for Kees Blom's railroad program +#diagram:token NAME +#diagram:token NUMBER +#diagram:token STRING +#diagram:token NEWLINE +#diagram:token ENDMARKER +#diagram:token INDENT +#diagram:output\input python.bla +#diagram:token DEDENT +#diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm +#diagram:rules + +# Start symbols for the grammar: +# single_input is a single interactive statement; +# file_input is a module or sequence of commands read from an input file; +# eval_input is the input for the eval() and input() functions. +# NB: compound_stmt in single_input is followed by extra NEWLINE! +single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE +file_input: (NEWLINE | stmt)* ENDMARKER +eval_input: testlist NEWLINE* ENDMARKER + +decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE +decorators: decorator+ +funcdef: [decorators] 'def' NAME parameters ':' suite +parameters: '(' [varargslist] ')' +varargslist: ((fpdef ['=' test] ',')* + ('*' NAME [',' '**' NAME] | '**' NAME) | + fpdef ['=' test] (',' fpdef ['=' test])* [',']) +fpdef: NAME | '(' fplist ')' +fplist: fpdef (',' fpdef)* [','] + +stmt: simple_stmt | compound_stmt +simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE +small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | + import_stmt | global_stmt | exec_stmt | assert_stmt) +expr_stmt: testlist (augassign (yield_expr|testlist) | + ('=' (yield_expr|testlist))*) +augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | + '<<=' | '>>=' | '**=' | '//=') +# For normal assignments, additional restrictions enforced by the interpreter +print_stmt: 'print' ( [ test (',' test)* [','] ] | + '>>' test [ (',' test)+ [','] ] ) +del_stmt: 'del' exprlist +pass_stmt: 'pass' +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt +break_stmt: 'break' +continue_stmt: 'continue' +return_stmt: 'return' [testlist] +yield_stmt: yield_expr +raise_stmt: 'raise' [test [',' test [',' test]]] +import_stmt: import_name | import_from +import_name: 'import' dotted_as_names +import_from: ('from' ('.'* dotted_name | '.'+) + 'import' ('*' | '(' import_as_names ')' | import_as_names)) +import_as_name: NAME [('as' | NAME) NAME] +dotted_as_name: dotted_name [('as' | NAME) NAME] +import_as_names: import_as_name (',' import_as_name)* [','] +dotted_as_names: dotted_as_name (',' dotted_as_name)* +dotted_name: NAME ('.' NAME)* +global_stmt: 'global' NAME (',' NAME)* +exec_stmt: 'exec' expr ['in' test [',' test]] +assert_stmt: 'assert' test [',' test] + +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef +if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] +while_stmt: 'while' test ':' suite ['else' ':' suite] +for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] +try_stmt: ('try' ':' suite + ((except_clause ':' suite)+ + ['else' ':' suite] + ['finally' ':' suite] | + 'finally' ':' suite)) +with_stmt: 'with' test [ with_var ] ':' suite +with_var: ('as' | NAME) expr +# NB compile.c makes sure that the default except clause is last +except_clause: 'except' [test [',' test]] +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT + +# Backward compatibility cruft to support: +# [ x for x in lambda: True, lambda: False if x() ] +# even while also allowing: +# lambda x: 5 if x else 2 +# (But not a mix of the two) +testlist_safe: old_test [(',' old_test)+ [',']] +old_test: or_test | old_lambdef +old_lambdef: 'lambda' [varargslist] ':' old_test + +test: or_test ['if' or_test 'else' test] | lambdef +or_test: and_test ('or' and_test)* +and_test: not_test ('and' not_test)* +not_test: 'not' not_test | comparison +comparison: expr (comp_op expr)* +comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' +expr: xor_expr ('|' xor_expr)* +xor_expr: and_expr ('^' and_expr)* +and_expr: shift_expr ('&' shift_expr)* +shift_expr: arith_expr (('<<'|'>>') arith_expr)* +arith_expr: term (('+'|'-') term)* +term: factor (('*'|'/'|'%'|'//') factor)* +factor: ('+'|'-'|'~') factor | power +power: atom trailer* ['**' factor] +atom: ('(' [yield_expr|testlist_gexp] ')' | + '[' [listmaker] ']' | + '{' [dictmaker] '}' | + '`' testlist1 '`' | + NAME | NUMBER | STRING+) +listmaker: test ( list_for | (',' test)* [','] ) +testlist_gexp: test ( gen_for | (',' test)* [','] ) +lambdef: 'lambda' [varargslist] ':' test +trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +subscriptlist: subscript (',' subscript)* [','] +subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] +sliceop: ':' [test] +exprlist: expr (',' expr)* [','] +testlist: test (',' test)* [','] +dictmaker: test ':' test (',' test ':' test)* [','] + +classdef: 'class' NAME ['(' [testlist] ')'] ':' suite + +arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +argument: test [gen_for] | test '=' test # Really [keyword '='] test + +list_iter: list_for | list_if +list_for: 'for' exprlist 'in' testlist_safe [list_iter] +list_if: 'if' old_test [list_iter] + +gen_iter: gen_for | gen_if +gen_for: 'for' exprlist 'in' or_test [gen_iter] +gen_if: 'if' old_test [gen_iter] + +testlist1: test (',' test)* + +# not used in grammar, but may appear in "node" passed from Parser to Compiler +encoding_decl: NAME + +yield_expr: 'yield' [testlist] Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py Fri Jun 4 01:02:42 2010 @@ -9,7 +9,7 @@ def _get_python_grammar(): here = os.path.dirname(__file__) - fp = open(os.path.join(here, "data", "Grammar2.5")) + fp = open(os.path.join(here, "data", "Grammar2.7")) try: gram_source = fp.read() finally: From benjamin at codespeak.net Fri Jun 4 01:05:42 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:05:42 +0200 (CEST) Subject: [pypy-svn] r75090 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler/test pyparser/data Message-ID: <20100603230542.DAB0136C394@codespeak.net> Author: benjamin Date: Fri Jun 4 01:05:41 2010 New Revision: 75090 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Log: implement 'as' in except clauses Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Fri Jun 4 01:05:41 2010 @@ -405,6 +405,15 @@ assert isinstance(h2.type, ast.Name) assert h2.name is None assert isinstance(h2.body[0], ast.Pass) + tr = self.get_first_stmt("try: x\nexcept Exc as a: 5\nexcept F: pass") + assert len(tr.handlers) == 2 + h1, h2 = tr.handlers + assert isinstance(h1.type, ast.Name) + assert isinstance(h1.name, ast.Name) + assert isinstance(h1.body[0].value, ast.Num) + assert isinstance(h2.type, ast.Name) + assert h2.name is None + assert isinstance(h2.body[0], ast.Pass) tr = self.get_first_stmt("try: x\nexcept: 4\nfinally: pass") assert isinstance(tr, ast.TryFinally) assert len(tr.finalbody) == 1 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Fri Jun 4 01:05:41 2010 @@ -85,7 +85,7 @@ with_stmt: 'with' test [ with_var ] ':' suite with_var: ('as' | NAME) expr # NB compile.c makes sure that the default except clause is last -except_clause: 'except' [test [',' test]] +except_clause: 'except' [test [('as' | ',') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: From benjamin at codespeak.net Fri Jun 4 01:17:26 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:17:26 +0200 (CEST) Subject: [pypy-svn] r75091 - pypy/branch/fast-forward/pypy/lib Message-ID: <20100603231726.875B836C374@codespeak.net> Author: benjamin Date: Fri Jun 4 01:17:24 2010 New Revision: 75091 Added: pypy/branch/fast-forward/pypy/lib/_collections.py - copied unchanged from r75086, pypy/branch/fast-forward/pypy/lib/collections.py Removed: pypy/branch/fast-forward/pypy/lib/collections.py Log: move pure python collections to _collections From hpk at codespeak.net Fri Jun 4 01:18:55 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 4 Jun 2010 01:18:55 +0200 (CEST) Subject: [pypy-svn] r75092 - pypy/trunk/lib-python Message-ID: <20100603231855.A5EA336C374@codespeak.net> Author: hpk Date: Fri Jun 4 01:18:53 2010 New Revision: 75092 Modified: pypy/trunk/lib-python/conftest.py Log: fix collection of lib-python tests under py.py Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Fri Jun 4 01:18:53 2010 @@ -532,7 +532,8 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + if path.basename == "test": + return RegrDirectory(path, parent) class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): From benjamin at codespeak.net Fri Jun 4 01:21:04 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:21:04 +0200 (CEST) Subject: [pypy-svn] r75093 - pypy/branch/fast-forward/pypy/lib Message-ID: <20100603232104.6554E36C374@codespeak.net> Author: benjamin Date: Fri Jun 4 01:21:03 2010 New Revision: 75093 Removed: pypy/branch/fast-forward/pypy/lib/functools.py Log: remove old functools.py From benjamin at codespeak.net Fri Jun 4 01:21:34 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:21:34 +0200 (CEST) Subject: [pypy-svn] r75094 - pypy/branch/fast-forward/pypy/lib Message-ID: <20100603232134.6643636C374@codespeak.net> Author: benjamin Date: Fri Jun 4 01:21:33 2010 New Revision: 75094 Modified: pypy/branch/fast-forward/pypy/lib/_functools.py Log: provide reduce alias in functools Modified: pypy/branch/fast-forward/pypy/lib/_functools.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/_functools.py (original) +++ pypy/branch/fast-forward/pypy/lib/_functools.py Fri Jun 4 01:21:33 2010 @@ -1,5 +1,8 @@ """ Supplies the internal functions for functools.py in the standard library """ +# reduce() has moved to _functools in Python 2.6+. +reduce = reduce + class partial: """ partial(func, *args, **keywords) - new function with partial application From benjamin at codespeak.net Fri Jun 4 01:33:42 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:33:42 +0200 (CEST) Subject: [pypy-svn] r75095 - pypy/branch/fast-forward/lib-python Message-ID: <20100603233342.310C536C536@codespeak.net> Author: benjamin Date: Fri Jun 4 01:33:40 2010 New Revision: 75095 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: run without site until sys.prefix can be figured out Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Fri Jun 4 01:33:40 2010 @@ -664,7 +664,7 @@ pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) sopt = " ".join(pypy_options) - cmd = "%s %s %d %s %s %s %s %s" %( + cmd = "%s %s %d %s -S %s %s %s %s" %( python, alarm_script, TIMEOUT, pypy_script, sopt, regrrun, regrrun_verbosity, fspath.purebasename) From benjamin at codespeak.net Fri Jun 4 01:34:47 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:34:47 +0200 (CEST) Subject: [pypy-svn] r75096 - pypy/branch/fast-forward/pypy/config Message-ID: <20100603233447.C1B7A36C536@codespeak.net> Author: benjamin Date: Fri Jun 4 01:34:46 2010 New Revision: 75096 Modified: pypy/branch/fast-forward/pypy/config/pypyoption.py Log: make signal essential; it's now used by unittest Modified: pypy/branch/fast-forward/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/fast-forward/pypy/config/pypyoption.py (original) +++ pypy/branch/fast-forward/pypy/config/pypyoption.py Fri Jun 4 01:34:46 2010 @@ -11,7 +11,7 @@ and p.join('__init__.py').check()] essential_modules = dict.fromkeys( - ["exceptions", "_file", "sys", "__builtin__", "posix"] + ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"] ) default_modules = essential_modules.copy() From benjamin at codespeak.net Fri Jun 4 01:35:48 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 01:35:48 +0200 (CEST) Subject: [pypy-svn] r75097 - pypy/branch/fast-forward/lib-python Message-ID: <20100603233548.B923D36C536@codespeak.net> Author: benjamin Date: Fri Jun 4 01:35:47 2010 New Revision: 75097 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: some more core tests Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Fri Jun 4 01:35:47 2010 @@ -297,8 +297,8 @@ RegrTest('test_importhooks.py', core=True), RegrTest('test_importlib.py'), RegrTest('test_inspect.py'), - RegrTest('test_int.py'), - RegrTest('test_int_literal.py'), + RegrTest('test_int.py', core=True), + RegrTest('test_int_literal.py', core=True), RegrTest('test_io.py'), RegrTest('test_ioctl.py'), RegrTest('test_isinstance.py', core=True), From arigo at codespeak.net Fri Jun 4 11:13:55 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 11:13:55 +0200 (CEST) Subject: [pypy-svn] r75098 - pypy/trunk/lib-python Message-ID: <20100604091355.B65F9282BD6@codespeak.net> Author: arigo Date: Fri Jun 4 11:13:54 2010 New Revision: 75098 Modified: pypy/trunk/lib-python/conftest.py Log: Revert r75092. It causes massive failures of the nightly applevel tests. I think (by running pypy-c py.test --collect) that it is because in this case it causes py.test to try to collect far more stuff, including both the 2.5.2/test and the modified-2.5.2/test version of the same test. Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Fri Jun 4 11:13:54 2010 @@ -532,8 +532,7 @@ return l def pytest_collect_directory(parent, path): - if path.basename == "test": - return RegrDirectory(path, parent) + return RegrDirectory(path, parent) class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): From arigo at codespeak.net Fri Jun 4 11:47:37 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 11:47:37 +0200 (CEST) Subject: [pypy-svn] r75099 - pypy/build/bot2/pypybuildbot Message-ID: <20100604094737.D51B7282BD6@codespeak.net> Author: arigo Date: Fri Jun 4 11:47:36 2010 New Revision: 75099 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Remove the --force-host option, which does not make sense now that we don't run on bigdog any more. Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 4 11:47:36 2010 @@ -150,7 +150,7 @@ description="run benchmarks on top of pypy-c-jit", command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', pypy_c_rel, - '--upload', '--force-host', 'bigdog', + '--upload', #'--force-host', 'bigdog', '--revision', WithProperties('%(got_revision)s'), '--branch', WithProperties('%(branch)s')], workdir='./benchmarks', @@ -165,7 +165,7 @@ command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', '../build/pypy/translator/goal/pypy-c', '--revision', WithProperties('%(got_revision)s'), - '--upload', '--force-host', 'bigdog', + '--upload', #'--force-host', 'bigdog', '--branch', WithProperties('%(branch)s'), '--args', ',--jit threshold=1000000000'], workdir='./benchmarks', @@ -180,7 +180,7 @@ command=["python", "runner.py", '--output-filename', 'result.json', '--pypy-c', 'psyco/python_with_psyco.sh', '--revision', WithProperties('%(got_revision)s'), - '--upload', '--force-host', 'bigdog', + '--upload', #'--force-host', 'bigdog', '--branch', WithProperties('%(branch)s'), ], workdir='./benchmarks', From arigo at codespeak.net Fri Jun 4 12:34:41 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 12:34:41 +0200 (CEST) Subject: [pypy-svn] r75100 - pypy/benchmarks Message-ID: <20100604103441.0C6CC282BD6@codespeak.net> Author: arigo Date: Fri Jun 4 12:34:40 2010 New Revision: 75100 Modified: pypy/benchmarks/saveresults.py Log: To be sure: check explicitly if we *can* contact speed.pypy.org before using the URL and reporting possibly obscured errors. Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Fri Jun 4 12:34:40 2010 @@ -55,6 +55,9 @@ info = str(datetime.today()) + ": Saving result for " + data['executable_name'] + " revision " info += str(data['commitid']) + ", benchmark " + data['benchmark'] print(info) + if not check_host_exists(SPEEDURL): + print "fail to contact the host of %s\n" % (SPEEDURL,) + return 1 try: f = urllib2.urlopen(SPEEDURL + 'result/add/', params) response = f.read() @@ -71,3 +74,11 @@ print "saved correctly!\n" return 0 +def check_host_exists(url): + import urlparse, socket + machinename = urlparse.urlparse(url)[1] + try: + socket.gethostbyname(machinename) + return True + except socket.gaierror: + return False From arigo at codespeak.net Fri Jun 4 12:51:42 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 12:51:42 +0200 (CEST) Subject: [pypy-svn] r75101 - pypy/benchmarks Message-ID: <20100604105142.DD3DC282BD6@codespeak.net> Author: arigo Date: Fri Jun 4 12:51:41 2010 New Revision: 75101 Modified: pypy/benchmarks/saveresults.py Log: Revert r75100. Found out the issue, will be documented. Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Fri Jun 4 12:51:41 2010 @@ -55,9 +55,6 @@ info = str(datetime.today()) + ": Saving result for " + data['executable_name'] + " revision " info += str(data['commitid']) + ", benchmark " + data['benchmark'] print(info) - if not check_host_exists(SPEEDURL): - print "fail to contact the host of %s\n" % (SPEEDURL,) - return 1 try: f = urllib2.urlopen(SPEEDURL + 'result/add/', params) response = f.read() @@ -74,11 +71,3 @@ print "saved correctly!\n" return 0 -def check_host_exists(url): - import urlparse, socket - machinename = urlparse.urlparse(url)[1] - try: - socket.gethostbyname(machinename) - return True - except socket.gaierror: - return False From arigo at codespeak.net Fri Jun 4 13:09:06 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 13:09:06 +0200 (CEST) Subject: [pypy-svn] r75102 - pypy/benchmarks/own/twisted Message-ID: <20100604110906.AB76936C536@codespeak.net> Author: arigo Date: Fri Jun 4 13:09:05 2010 New Revision: 75102 Modified: pypy/benchmarks/own/twisted/benchlib.py Log: Add a sleep of 90 seconds at the end of any twisted benchmark that creates a lot of connections. This should solve the issues like DNS errors just afterwards, by giving the system enough time to purge the mess of local TCP connections in the TIME_WAIT state. Modified: pypy/benchmarks/own/twisted/benchlib.py ============================================================================== --- pypy/benchmarks/own/twisted/benchlib.py (original) +++ pypy/benchmarks/own/twisted/benchlib.py Fri Jun 4 13:09:05 2010 @@ -80,6 +80,7 @@ d.addErrback(log.err) reactor.callWhenRunning(d.addBoth, lambda ign: reactor.stop()) reactor.run() + sleep_to_purge_connexions() sys.exit(failure) def multidriver(*f): @@ -92,9 +93,21 @@ reactor.stop() reactor.callWhenRunning(work) reactor.run() + sleep_to_purge_connexions() _interface = 1 def rotate_local_intf(): global _interface _interface = _interface % 254 + 1 return '127.0.0.%d' % (_interface,) + +def sleep_to_purge_connexions(): + # For tests that do a lot of TCP connexions, we sleep a bit more than + # 1 minute at the end. This makes sure that the sockets have time to + # get out of the TIME_WAIT state before we do anything more. + global _interface + if _interface != 1: + print >> sys.stderr, "sleeping 90 seconds..." + import time + time.sleep(90) + _interface = 1 From arigo at codespeak.net Fri Jun 4 14:53:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 14:53:50 +0200 (CEST) Subject: [pypy-svn] r75103 - pypy/benchmarks/own/twisted Message-ID: <20100604125350.30195282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 14:53:48 2010 New Revision: 75103 Modified: pypy/benchmarks/own/twisted/benchlib.py Log: Be "future-proof" and wait 2 minutes 5'' instead of 1 minute 30''. Just in case some machine has a 2 minutes delay. Modified: pypy/benchmarks/own/twisted/benchlib.py ============================================================================== --- pypy/benchmarks/own/twisted/benchlib.py (original) +++ pypy/benchmarks/own/twisted/benchlib.py Fri Jun 4 14:53:48 2010 @@ -103,11 +103,11 @@ def sleep_to_purge_connexions(): # For tests that do a lot of TCP connexions, we sleep a bit more than - # 1 minute at the end. This makes sure that the sockets have time to + # 2 minutes at the end. This makes sure that the sockets have time to # get out of the TIME_WAIT state before we do anything more. global _interface if _interface != 1: - print >> sys.stderr, "sleeping 90 seconds..." + print >> sys.stderr, "sleeping 125 seconds..." import time - time.sleep(90) + time.sleep(125) _interface = 1 From arigo at codespeak.net Fri Jun 4 15:13:40 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 15:13:40 +0200 (CEST) Subject: [pypy-svn] r75104 - pypy/benchmarks/own/twisted Message-ID: <20100604131340.D12FF36C22E@codespeak.net> Author: arigo Date: Fri Jun 4 15:13:39 2010 New Revision: 75104 Modified: pypy/benchmarks/own/twisted/benchlib.py Log: A different hack: call 'netstat' and stop when there are few TIME_WAIT connections left. Modified: pypy/benchmarks/own/twisted/benchlib.py ============================================================================== --- pypy/benchmarks/own/twisted/benchlib.py (original) +++ pypy/benchmarks/own/twisted/benchlib.py Fri Jun 4 15:13:39 2010 @@ -105,9 +105,14 @@ # For tests that do a lot of TCP connexions, we sleep a bit more than # 2 minutes at the end. This makes sure that the sockets have time to # get out of the TIME_WAIT state before we do anything more. - global _interface - if _interface != 1: - print >> sys.stderr, "sleeping 125 seconds..." - import time - time.sleep(125) - _interface = 1 + print >> sys.stderr, "sleeping up to 132 seconds...", + import time, os + for i in range(24): + g = os.popen('netstat -atn') + data = g.read() + g.close() + if ('Active Internet connections' in data and + data.count('TIME_WAIT') < 20): + break + time.sleep(5.5) + print >> sys.stderr, "done" From hpk at codespeak.net Fri Jun 4 15:16:40 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 4 Jun 2010 15:16:40 +0200 (CEST) Subject: [pypy-svn] r75105 - pypy/branch/lib-python Message-ID: <20100604131640.B4D1436C22E@codespeak.net> Author: hpk Date: Fri Jun 4 15:16:38 2010 New Revision: 75105 Added: pypy/branch/lib-python/ (props changed) - copied from r75104, pypy/trunk/ Log: trying out lib-python tests From arigo at codespeak.net Fri Jun 4 15:48:21 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 15:48:21 +0200 (CEST) Subject: [pypy-svn] r75106 - in pypy/trunk/pypy/module/imp: . test Message-ID: <20100604134821.1A4FF282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 15:48:20 2010 New Revision: 75106 Modified: pypy/trunk/pypy/module/imp/importing.py pypy/trunk/pypy/module/imp/test/test_import.py Log: Test and fix. Modified: pypy/trunk/pypy/module/imp/importing.py ============================================================================== --- pypy/trunk/pypy/module/imp/importing.py (original) +++ pypy/trunk/pypy/module/imp/importing.py Fri Jun 4 15:48:20 2010 @@ -145,7 +145,7 @@ msg = "Attempted relative import in non-package" raise OperationError(space.w_ValueError, w(msg)) w_mod = absolute_import_try(space, modulename, 0, fromlist_w) - if w_mod is None and not space.is_w(w_mod, space.w_None): + if w_mod is None or space.is_w(w_mod, space.w_None): w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0) if rel_modulename is not None: space.setitem(space.sys.get('modules'), w(rel_modulename), space.w_None) Modified: pypy/trunk/pypy/module/imp/test/test_import.py ============================================================================== --- pypy/trunk/pypy/module/imp/test/test_import.py (original) +++ pypy/trunk/pypy/module/imp/test/test_import.py Fri Jun 4 15:48:20 2010 @@ -457,6 +457,16 @@ def test_reload_infinite(self): import infinite_reload + def test_explicitly_missing(self): + import sys + sys.modules['foobarbazmod'] = None + try: + import foobarbazmod + assert False, "should have failed, got instead %r" % ( + foobarbazmod,) + except ImportError: + pass + def _getlong(data): x = marshal.dumps(data) return x[-4:] From arigo at codespeak.net Fri Jun 4 16:04:47 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 16:04:47 +0200 (CEST) Subject: [pypy-svn] r75107 - pypy/branch/blackhole-improvement/pypy/jit/tl/spli Message-ID: <20100604140447.9C2BC282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 16:04:46 2010 New Revision: 75107 Modified: pypy/branch/blackhole-improvement/pypy/jit/tl/spli/interpreter.py Log: Reorder green vars. Modified: pypy/branch/blackhole-improvement/pypy/jit/tl/spli/interpreter.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/tl/spli/interpreter.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/tl/spli/interpreter.py Fri Jun 4 16:04:46 2010 @@ -24,7 +24,7 @@ unrolling_compare_dispatch_table = unrolling_iterable( enumerate(compare_ops)) -jitdriver = JitDriver(greens = ['code', 'instr_index'], +jitdriver = JitDriver(greens = ['instr_index', 'code'], reds = ['frame'], virtualizables = ['frame']) From arigo at codespeak.net Fri Jun 4 16:10:40 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 16:10:40 +0200 (CEST) Subject: [pypy-svn] r75108 - in pypy/branch/blackhole-improvement/pypy/jit: metainterp tool tool/test Message-ID: <20100604141040.6489C282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 16:10:38 2010 New Revision: 75108 Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/jitprof.py pypy/branch/blackhole-improvement/pypy/jit/tool/jitoutput.py pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py Log: Fix for test_jitoutput. Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/jitprof.py Fri Jun 4 16:10:38 2010 @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 5 # one for TOTAL, 5 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 4 # one for TOTAL, 4 for calls, update if needed class BaseProfiler(object): pass Modified: pypy/branch/blackhole-improvement/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/tool/jitoutput.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/tool/jitoutput.py Fri Jun 4 16:10:38 2010 @@ -21,8 +21,6 @@ (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), - (('blackholed_ops.total',), '^blackholed ops:\s+(\d+)$'), - (('blackholed_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), (('forcings',), '^forcings:\s+(\d+)$'), @@ -62,7 +60,6 @@ def __init__(self): self.ops = Ops() self.recorded_ops = Ops() - self.blackholed_ops = Ops() self.abort = Aborts() def parse_prof(output): Modified: pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py Fri Jun 4 16:10:38 2010 @@ -59,8 +59,6 @@ calls: 3 pure calls: 2 guards: 1 -blackholed ops: 5 - pure calls: 3 opt ops: 6 opt guards: 1 forcings: 1 @@ -87,8 +85,6 @@ assert info.recorded_ops.calls == 3 assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 - assert info.blackholed_ops.total == 5 - assert info.blackholed_ops.pure_calls == 3 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 1 From hpk at codespeak.net Fri Jun 4 16:43:08 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 4 Jun 2010 16:43:08 +0200 (CEST) Subject: [pypy-svn] r75109 - pypy/branch/lib-python/lib-python Message-ID: <20100604144308.70F87282B9E@codespeak.net> Author: hpk Date: Fri Jun 4 16:43:06 2010 New Revision: 75109 Modified: pypy/branch/lib-python/lib-python/conftest.py Log: new try to sanitize lib-python testing Modified: pypy/branch/lib-python/lib-python/conftest.py ============================================================================== --- pypy/branch/lib-python/lib-python/conftest.py (original) +++ pypy/branch/lib-python/lib-python/conftest.py Fri Jun 4 16:43:06 2010 @@ -520,11 +520,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -532,7 +535,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): From afa at codespeak.net Fri Jun 4 17:16:40 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 17:16:40 +0200 (CEST) Subject: [pypy-svn] r75110 - pypy/trunk/pypy/module/cpyext Message-ID: <20100604151640.65BCB282B9E@codespeak.net> Author: afa Date: Fri Jun 4 17:16:38 2010 New Revision: 75110 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Fix test failures. I probably wrote 500 lines of code before I found the mistake. Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Fri Jun 4 17:16:38 2010 @@ -656,12 +656,13 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): - in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) if name.startswith('PyPyExc_'): # we already have the pointer + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) else: # we have a structure, get its address + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) From afa at codespeak.net Fri Jun 4 17:17:21 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 17:17:21 +0200 (CEST) Subject: [pypy-svn] r75111 - pypy/trunk/pypy/module/cpyext Message-ID: <20100604151721.6988E282B9E@codespeak.net> Author: afa Date: Fri Jun 4 17:17:19 2010 New Revision: 75111 Modified: pypy/trunk/pypy/module/cpyext/pyobject.py pypy/trunk/pypy/module/cpyext/typeobject.py Log: Little cleanup Modified: pypy/trunk/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/pyobject.py (original) +++ pypy/trunk/pypy/module/cpyext/pyobject.py Fri Jun 4 17:17:19 2010 @@ -2,9 +2,9 @@ from pypy.interpreter.baseobjspace import W_Root, SpaceCache from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, bootstrap_function, \ - PyObject, PyObjectP, ADDR, CANNOT_FAIL, \ - Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr +from pypy.module.cpyext.api import ( + cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR, + CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) from pypy.module.cpyext.state import State from pypy.objspace.std.typeobject import W_TypeObject from pypy.rlib.objectmodel import specialize, we_are_translated @@ -263,9 +263,9 @@ Allocates a PyObject, and fills its fields with info from the given intepreter object. """ + state = space.fromcache(RefcountState) w_type = space.type(w_obj) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) py_obj = state.get_from_lifeline(w_obj) if py_obj: Py_IncRef(space, py_obj) @@ -274,7 +274,6 @@ typedescr = get_typedescr(w_obj.typedef) py_obj = typedescr.allocate(space, w_type, itemcount=itemcount) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) state.set_lifeline(w_obj, py_obj) typedescr.attach(space, py_obj, w_obj) return py_obj @@ -333,7 +332,7 @@ # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) - if ref_type == ref: + if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) Modified: pypy/trunk/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/typeobject.py Fri Jun 4 17:17:19 2010 @@ -376,8 +376,8 @@ @cpython_api([PyObject], lltype.Void, external=False) def type_dealloc(space, obj): + from pypy.module.cpyext.object import PyObject_dealloc obj_pto = rffi.cast(PyTypeObjectPtr, obj) - type_pto = obj.c_ob_type base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base) Py_DecRef(space, obj_pto.c_tp_bases) Py_DecRef(space, obj_pto.c_tp_mro) @@ -389,11 +389,7 @@ lltype.free(obj_pto.c_tp_as_number, flavor='raw') Py_DecRef(space, base_pyo) rffi.free_charp(obj_pto.c_tp_name) - obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto) - generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp) - if type_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: - pto = rffi.cast(PyObject, type_pto) - Py_DecRef(space, pto) + PyObject_dealloc(space, obj) def type_attach(space, py_obj, w_type): From arigo at codespeak.net Fri Jun 4 17:26:55 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 17:26:55 +0200 (CEST) Subject: [pypy-svn] r75112 - pypy/branch/blackhole-improvement/pypy/jit/tl/tla Message-ID: <20100604152655.6C2AA282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 17:26:53 2010 New Revision: 75112 Modified: pypy/branch/blackhole-improvement/pypy/jit/tl/tla/tla.py Log: Reorder the green vars. Modified: pypy/branch/blackhole-improvement/pypy/jit/tl/tla/tla.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/tl/tla/tla.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/tl/tla/tla.py Fri Jun 4 17:26:53 2010 @@ -71,10 +71,10 @@ # ____________________________________________________________ -def get_printable_location(bytecode, pc): +def get_printable_location(pc, bytecode): return str(pc) -jitdriver = JitDriver(greens=['bytecode', 'pc'], +jitdriver = JitDriver(greens=['pc', 'bytecode'], reds=['self'], virtualizables=['self'], get_printable_location=get_printable_location) From hpk at codespeak.net Fri Jun 4 17:45:19 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 4 Jun 2010 17:45:19 +0200 (CEST) Subject: [pypy-svn] r75113 - pypy/trunk/lib-python Message-ID: <20100604154519.6032A282B9E@codespeak.net> Author: hpk Date: Fri Jun 4 17:45:17 2010 New Revision: 75113 Modified: pypy/trunk/lib-python/conftest.py Log: try to redo the fix related to testing in lib-python. Tests are now collected more "normally" in their respective directories 2.5.2/test and modified-2.5.2/test instead of "faking" an artifical tree at lib-python level. Note that you will get a collection error if you run a specific test via "py.ttest lib-python/2.5.2/test/test_XYZ.py" if there is a test_XYZ in the modified-2.5.2 directory. Running "py.test lib-python" or "py.test --pypy=pypy-c lib-python" will run both modified and unmodified tests as is to be expected and filenames during testing progress clearly indicate where a test comes from. Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Fri Jun 4 17:45:17 2010 @@ -520,11 +520,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -532,7 +535,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): From hpk at codespeak.net Fri Jun 4 17:46:09 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 4 Jun 2010 17:46:09 +0200 (CEST) Subject: [pypy-svn] r75114 - pypy/branch/lib-python Message-ID: <20100604154609.11A2E282B9E@codespeak.net> Author: hpk Date: Fri Jun 4 17:46:08 2010 New Revision: 75114 Removed: pypy/branch/lib-python/ Log: remove lib-python branch, seems buildbot jobs do fine From arigo at codespeak.net Fri Jun 4 18:00:08 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 18:00:08 +0200 (CEST) Subject: [pypy-svn] r75115 - in pypy/branch/blackhole-improvement/pypy: annotation rpython rpython/lltypesystem rpython/test translator/c/src Message-ID: <20100604160008.D603C282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 18:00:06 2010 New Revision: 75115 Modified: pypy/branch/blackhole-improvement/pypy/annotation/builtin.py pypy/branch/blackhole-improvement/pypy/rpython/llinterp.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llmemory.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rffi.py pypy/branch/blackhole-improvement/pypy/rpython/rbuiltin.py pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py pypy/branch/blackhole-improvement/pypy/translator/c/src/address.h Log: Refactor cast_adr_to_int(), step 1. Modified: pypy/branch/blackhole-improvement/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/annotation/builtin.py (original) +++ pypy/branch/blackhole-improvement/pypy/annotation/builtin.py Fri Jun 4 18:00:06 2010 @@ -340,7 +340,7 @@ assert s_type.is_constant() return SomePtr(s_type.const) -def llmemory_cast_adr_to_int(s): +def llmemory_cast_adr_to_int(s, s_mode=None): return SomeInteger() # xxx def llmemory_cast_int_to_adr(s): Modified: pypy/branch/blackhole-improvement/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/llinterp.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/llinterp.py Fri Jun 4 18:00:06 2010 @@ -793,9 +793,9 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) - def op_cast_adr_to_int(self, adr): + def op_cast_adr_to_int(self, adr, mode): checkadr(adr) - return llmemory.cast_adr_to_int(adr) + return llmemory.cast_adr_to_int(adr, mode) def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llmemory.py Fri Jun 4 18:00:06 2010 @@ -479,9 +479,14 @@ else: return lltype.nullptr(EXPECTED_TYPE.TO) - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): if self: - return AddressAsInt(self) + if symbolic: + return AddressAsInt(self) + else: + # This is a bit annoying. We want this method to still work + # when the pointed-to object is dead + return self.ptr._cast_to_int(False) else: return 0 @@ -625,8 +630,21 @@ def cast_adr_to_ptr(adr, EXPECTED_TYPE): return adr._cast_to_ptr(EXPECTED_TYPE) -def cast_adr_to_int(adr): - return adr._cast_to_int() +def cast_adr_to_int(adr, mode="emulated"): + # The following modes are supported before translation (after + # translation, it's all just a cast): + # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some + # number based on id(). The difference is that it works even if the + # address is that of a dead object. + # * mode="symbolic": returns an AddressAsInt instance, which can only be + # cast back to an address later. + # * mode="forced": uses rffi.cast() to return a real number. + assert mode in ("emulated", "symbolic", "forced") + res = adr._cast_to_int(symbolic = (mode != "emulated")) + if mode == "forced": + from pypy.rpython.lltypesystem.rffi import cast + res = cast(lltype.Signed, res) + return res _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rffi.py Fri Jun 4 18:00:06 2010 @@ -905,11 +905,3 @@ """ return cast(lltype.Signed, getattr(pdst, fieldname)) getintfield._annspecialcase_ = 'specialize:ll_and_arg(1)' - -def get_real_int(i): - """No-op after translation. Before translation, it convert an - AddressAsInt into a real integer, to use e.g. as a hash. Do not store - the real integer (or the dict using this as a hash) across translation.""" - # although it's not really a cast, this force_cast forces - # the AddressAsInt to be evaluated with ctypes - return cast(lltype.Signed, i) Modified: pypy/branch/blackhole-improvement/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/rbuiltin.py Fri Jun 4 18:00:06 2010 @@ -604,9 +604,14 @@ def rtype_cast_adr_to_int(hop): assert isinstance(hop.args_r[0], raddress.AddressRepr) - adr, = hop.inputargs(hop.args_r[0]) + adr = hop.inputarg(hop.args_r[0], arg=0) + if len(hop.args_s) == 1: + mode = "emulated" + else: + mode = hop.args_s[1].const hop.exception_cannot_occur() - return hop.genop('cast_adr_to_int', [adr], + return hop.genop('cast_adr_to_int', + [adr, hop.inputconst(lltype.Void, mode)], resulttype = lltype.Signed) def rtype_cast_int_to_adr(hop): Modified: pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py Fri Jun 4 18:00:06 2010 @@ -176,6 +176,31 @@ res = interpret(fn, [5]) assert res is True +def test_cast_adr_to_int(): + S = Struct('S') + p = malloc(S, immortal=True) + def fn(n): + a = llmemory.cast_ptr_to_adr(p) + if n == 2: + return llmemory.cast_adr_to_int(a, "emulated") + elif n == 4: + return llmemory.cast_adr_to_int(a, "symbolic") + else: + return llmemory.cast_adr_to_int(a, "forced") + + res = interpret(fn, [2]) + assert type(res) is int + assert res == cast_ptr_to_int(p) + # + res = interpret(fn, [4]) + assert isinstance(res, llmemory.AddressAsInt) + assert llmemory.cast_int_to_adr(res) == llmemory.cast_ptr_to_adr(p) + # + res = interpret(fn, [6]) + assert type(res) is int + from pypy.rpython.lltypesystem import rffi + assert res == rffi.cast(Signed, p) + def test_flavored_malloc(): T = GcStruct('T', ('y', Signed)) def fn(n): Modified: pypy/branch/blackhole-improvement/pypy/translator/c/src/address.h ============================================================================== --- pypy/branch/blackhole-improvement/pypy/translator/c/src/address.h (original) +++ pypy/branch/blackhole-improvement/pypy/translator/c/src/address.h Fri Jun 4 18:00:06 2010 @@ -16,5 +16,5 @@ #define OP_ADR_LT(x,y,r) r = ((x) < (y)) #define OP_ADR_GE(x,y,r) r = ((x) >= (y)) -#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x) -#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) +#define OP_CAST_ADR_TO_INT(x, mode, r) r = ((long)x) +#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) From arigo at codespeak.net Fri Jun 4 18:10:41 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 18:10:41 +0200 (CEST) Subject: [pypy-svn] r75116 - pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem Message-ID: <20100604161041.CF23F282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 18:10:40 2010 New Revision: 75116 Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llarena.py Log: Fix. Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/llarena.py Fri Jun 4 18:10:40 2010 @@ -223,7 +223,8 @@ else: return self.arena._getid() < arena._getid() - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): + assert not symbolic return self.arena._getid() + self.offset From arigo at codespeak.net Fri Jun 4 19:24:26 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jun 2010 19:24:26 +0200 (CEST) Subject: [pypy-svn] r75117 - in pypy/branch/blackhole-improvement/pypy: jit/backend jit/backend/llgraph jit/backend/llgraph/test jit/backend/llsupport jit/backend/test jit/backend/x86 jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/test rpython rpython/lltypesystem/test rpython/memory/test Message-ID: <20100604172426.BEAD0282B9E@codespeak.net> Author: arigo Date: Fri Jun 4 19:24:22 2010 New Revision: 75117 Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/gc.py pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/llmodel.py pypy/branch/blackhole-improvement/pypy/jit/backend/model.py pypy/branch/blackhole-improvement/pypy/jit/backend/test/runner_test.py pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_ll_random.py pypy/branch/blackhole-improvement/pypy/jit/backend/x86/assembler.py pypy/branch/blackhole-improvement/pypy/jit/backend/x86/regalloc.py pypy/branch/blackhole-improvement/pypy/jit/backend/x86/ri386.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/heaptracker.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/logger.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/resoperation.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/oparser.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizefindnode.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_resume.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualref.py pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmstate.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/blackhole-improvement/pypy/rpython/memory/test/test_lldict.py pypy/branch/blackhole-improvement/pypy/rpython/raddress.py Log: Whole bunch of fixes in the jit: call heaptracker.adr2int(), which calls llmemory.cast_adr_to_int() with the new extra argument. Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py Fri Jun 4 19:24:22 2010 @@ -970,9 +970,9 @@ def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): - return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return llmemory.cast_adr_to_int(x) + return heaptracker.adr2int(x) return lltype.cast_primitive(lltype.Signed, x) def cast_from_int(TYPE, x): @@ -987,7 +987,7 @@ return x else: if lltype.typeOf(x) == llmemory.Address: - x = llmemory.cast_adr_to_int(x) + x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x) def cast_to_ptr(x): Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py Fri Jun 4 19:24:22 2010 @@ -15,6 +15,7 @@ from pypy.jit.backend import model from pypy.jit.backend.llgraph import llimpl, symbolic from pypy.jit.metainterp.typesystem import llhelper, oohelper +from pypy.jit.codewriter import heaptracker from pypy.rlib import rgc class MiniStats: @@ -254,7 +255,7 @@ def get_latest_force_token(self): token = llimpl.get_frame_forced_token(self.latest_frame) - return llmemory.cast_adr_to_int(token) + return heaptracker.adr2int(token) def clear_latest_values(self, count): llimpl.frame_clear_latest_values(self.latest_frame, count) @@ -357,7 +358,7 @@ struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result = struct.typeptr result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) - return llmemory.cast_adr_to_int(result_adr) + return heaptracker.adr2int(result_adr) def bh_new_array(self, arraydescr, length): assert isinstance(arraydescr, Descr) @@ -437,9 +438,6 @@ for x in args_f: llimpl.do_call_pushfloat(x) - def bh_cast_ptr_to_int(self, ptr): - return llimpl.cast_to_int(ptr) - def force(self, force_token): token = llmemory.cast_int_to_adr(force_token) frame = llimpl.get_forced_token_frame(token) Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Jun 4 19:24:22 2010 @@ -7,6 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.test.runner_test import LLtypeBackendTest class TestLLTypeLLGraph(LLtypeBackendTest): @@ -24,12 +25,12 @@ x = lltype.malloc(X, immortal=True) x.foo = 42 a = llmemory.cast_ptr_to_adr(x) - i = llmemory.cast_adr_to_int(a) + i = heaptracker.adr2int(a) assert lltype.typeOf(i) is lltype.Signed - a2 = llmemory.cast_int_to_adr(i) + a2 = heaptracker.int2adr(i) assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x - assert llmemory.cast_adr_to_int(llmemory.NULL) == 0 - assert llmemory.cast_int_to_adr(0) == llmemory.NULL + assert heaptracker.adr2int(llmemory.NULL) == 0 + assert heaptracker.int2adr(0) == llmemory.NULL ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/gc.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/gc.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/gc.py Fri Jun 4 19:24:22 2010 @@ -170,8 +170,7 @@ # first look in the hashtable, using an inexact hash (fails after # the object moves) addr = llmemory.cast_ptr_to_adr(gcref) - hash = llmemory.cast_adr_to_int(addr) - hash = rffi.get_real_int(hash) + hash = llmemory.cast_adr_to_int(addr, "forced") hash -= hash >> self.HASHTABLE_BITS hash &= self.HASHTABLE_SIZE - 1 addr_ref = self.hashtable[hash] Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/llmodel.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/llmodel.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/llsupport/llmodel.py Fri Jun 4 19:24:22 2010 @@ -7,6 +7,7 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\ BoxFloat from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.model import AbstractCPU from pypy.jit.backend.llsupport import symbolic from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes @@ -18,7 +19,6 @@ from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr from pypy.rpython.annlowlevel import cast_instance_to_base_ptr -empty_int_box = BoxInt(0) class AbstractLLCPU(AbstractCPU): from pypy.jit.metainterp.typesystem import llhelper as ts @@ -118,11 +118,11 @@ def pos_exception(): addr = llop.get_exception_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def save_exception(): addr = llop.get_exception_addr(llmemory.Address) @@ -422,7 +422,7 @@ struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result = struct.typeptr result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) - return llmemory.cast_adr_to_int(result_adr) + return heaptracker.adr2int(result_adr) def bh_new_array(self, arraydescr, length): return self.gc_ll_descr.gc_malloc_array(arraydescr, length) @@ -464,6 +464,3 @@ if not we_are_translated(): calldescr.verify_types(args_i, args_r, args_f, history.VOID) return calldescr.call_stub(func, args_i, args_r, args_f) - - def bh_cast_ptr_to_int(self, ptr): - return self.cast_gcref_to_int(ptr) Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/model.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/model.py Fri Jun 4 19:24:22 2010 @@ -217,9 +217,6 @@ def bh_call_v(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - def bh_cast_ptr_to_int(self, ptr): - raise NotImplementedError - def bh_strlen(self, string): raise NotImplementedError def bh_strgetitem(self, string, index): Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/test/runner_test.py Fri Jun 4 19:24:22 2010 @@ -1096,7 +1096,7 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): addr = llmemory.cast_ptr_to_adr(func_ptr) - return ConstInt(llmemory.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) MY_VTABLE = rclass.OBJECT_VTABLE # for tests only @@ -1128,7 +1128,7 @@ elif T == self.U: t.parent.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(llmemory.cast_adr_to_int(vtable_for_T_addr)) + T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr)) return t_box, T_box def null_instance(self): @@ -1157,22 +1157,23 @@ def test_casts(self): + py.test.skip("xxx fix or kill") from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') x = lltype.malloc(TP) x = lltype.cast_opaque_ptr(llmemory.GCREF, x) res = self.execute_operation(rop.CAST_PTR_TO_INT, [BoxPtr(x)], 'int').value - expected = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) assert rffi.get_real_int(res) == rffi.get_real_int(expected) res = self.execute_operation(rop.CAST_PTR_TO_INT, [ConstPtr(x)], 'int').value - expected = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) assert rffi.get_real_int(res) == rffi.get_real_int(expected) def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 1 r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int') @@ -1202,7 +1203,7 @@ S = lltype.Struct('S', ('x', lltype.Signed)) s = lltype.malloc(S, flavor='raw') sa = llmemory.cast_ptr_to_adr(s) - s_box = BoxInt(llmemory.cast_adr_to_int(sa)) + s_box = BoxInt(heaptracker.adr2int(sa)) for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW), (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)): fd = self.cpu.fielddescrof(S, 'x') @@ -1593,12 +1594,12 @@ rs = lltype.malloc(RS, immortal=True) rs.x = '?' x = cpu.bh_getfield_raw_i( - llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)), + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx) assert x == ord('?') # cpu.bh_setfield_raw_i( - llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)), + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx, ord('!')) assert rs.x == '!' # @@ -1636,7 +1637,7 @@ # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - vtable2_int = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)) + vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2)) heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT) x = cpu.bh_new_with_vtable(descrsize2, vtable2_int) lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check @@ -1662,12 +1663,12 @@ cpu.bh_strsetitem(x, 4, ord('/')) assert str.chars[4] == '/' # - x = cpu.bh_newstr(5) - y = cpu.bh_cast_ptr_to_int(x) - z = cpu.bh_cast_ptr_to_int(x) - y = rffi.get_real_int(y) - z = rffi.get_real_int(z) - assert type(y) == type(z) == int and y == z +## x = cpu.bh_newstr(5) +## y = cpu.bh_cast_ptr_to_int(x) +## z = cpu.bh_cast_ptr_to_int(x) +## y = rffi.get_real_int(y) +## z = rffi.get_real_int(z) +## assert type(y) == type(z) == int and y == z def test_sorting_of_fields(self): S = self.S @@ -1680,7 +1681,7 @@ def test_guards_nongc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) vbox = BoxInt(v) ops = [ (rop.GUARD_NONNULL, vbox, False), Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/test/test_ll_random.py Fri Jun 4 19:24:22 2010 @@ -182,7 +182,7 @@ # ____________________________________________________________ def ConstAddr(addr, cpu): - return ConstInt(llmemory.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/x86/assembler.py Fri Jun 4 19:24:22 2010 @@ -749,7 +749,7 @@ def genop_same_as(self, op, arglocs, resloc): self.mov(arglocs[0], resloc) - genop_cast_ptr_to_int = genop_same_as + #genop_cast_ptr_to_int = genop_same_as def genop_int_mod(self, op, arglocs, resloc): self.mc.CDQ() Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/x86/regalloc.py Fri Jun 4 19:24:22 2010 @@ -871,7 +871,7 @@ self.possibly_free_var(op.args[0]) resloc = self.force_allocate_reg(op.result) self.Perform(op, [argloc], resloc) - consider_cast_ptr_to_int = consider_same_as + #consider_cast_ptr_to_int = consider_same_as def consider_strlen(self, op): base_loc = self.rm.make_sure_var_in_reg(op.args[0], op.args) Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/x86/ri386.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/backend/x86/ri386.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/backend/x86/ri386.py Fri Jun 4 19:24:22 2010 @@ -1,7 +1,6 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated from pypy.rlib.debug import make_sure_not_resized -from pypy.rpython.lltypesystem.rffi import get_real_int class OPERAND(object): _attrs_ = [] @@ -287,6 +286,10 @@ rel32 = REL32 rel8 = REL8 +def get_real_int(x): + from pypy.rpython.lltypesystem import rffi, lltype + return rffi.cast(lltype.Signed, x) # force as a real int + def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py Fri Jun 4 19:24:22 2010 @@ -3,6 +3,7 @@ from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets from pypy.jit.codewriter.format import format_assembler from pypy.jit.codewriter.jitcode import SwitchDictDescr, JitCode +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import ComputedIntSymbolic from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem import lltype, llmemory, rclass @@ -69,7 +70,7 @@ value = llmemory.cast_ptr_to_adr(value) TYPE = llmemory.Address if TYPE == llmemory.Address: - value = llmemory.cast_adr_to_int(value) + value = heaptracker.adr2int(value) elif not isinstance(value, ComputedIntSymbolic): value = lltype.cast_primitive(lltype.Signed, value) if allow_short and -128 <= value <= 127: Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/heaptracker.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/heaptracker.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/heaptracker.py Fri Jun 4 19:24:22 2010 @@ -2,6 +2,16 @@ from pypy.rlib.objectmodel import we_are_translated +def adr2int(addr): + # Cast an address to an int. Returns an AddressAsInt object which + # can be cast back to an address. + return llmemory.cast_adr_to_int(addr, "symbolic") + +def int2adr(int): + return llmemory.cast_int_to_adr(int) + +# ____________________________________________________________ + def has_gcstruct_a_vtable(GCSTRUCT): if not isinstance(GCSTRUCT, lltype.GcStruct): return False @@ -69,7 +79,7 @@ def vtable2descr(cpu, vtable): assert lltype.typeOf(vtable) is lltype.Signed - vtable = llmemory.cast_int_to_adr(vtable) + vtable = int2adr(vtable) if we_are_translated(): # Build the dict {vtable: sizedescr} at runtime. # This is necessary because the 'vtables' are just pointers to @@ -94,5 +104,4 @@ assert isinstance(descr, history.AbstractDescr) vtable = descr.as_vtable_size_descr()._corresponding_vtable vtable = llmemory.cast_ptr_to_adr(vtable) - vtable = llmemory.cast_adr_to_int(vtable) - return vtable + return adr2int(vtable) Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py Fri Jun 4 19:24:22 2010 @@ -1,4 +1,5 @@ from pypy.jit.metainterp.history import AbstractDescr +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import llmemory @@ -33,7 +34,7 @@ self._alllabels = alllabels # debugging def get_fnaddr_as_int(self): - return llmemory.cast_adr_to_int(self.fnaddr) + return heaptracker.adr2int(self.fnaddr) def num_regs_i(self): return self.num_regs_encoded >> 16 Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py Fri Jun 4 19:24:22 2010 @@ -675,7 +675,8 @@ def rewrite_op_cast_ptr_to_int(self, op): if self._is_gc(op.args[0]): - return op + #return op + raise NotImplementedError("cast_ptr_to_int") # ---------- # Renames, from the _old opname to the _new one. Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py Fri Jun 4 19:24:22 2010 @@ -3,6 +3,7 @@ from pypy.jit.codewriter.flatten import SSARepr, Label, TLabel, Register from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets from pypy.jit.codewriter.jitcode import MissingLiveness +from pypy.jit.codewriter import heaptracker from pypy.jit.metainterp.history import AbstractDescr from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem import lltype, llmemory @@ -83,7 +84,7 @@ assert assembler.insns == {'int_return/c': 0, 'int_return/i': 1, 'ref_return/r': 2} - f_int = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(f)) + f_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(f)) assert jitcode.constants_i == [0x1234, f_int] s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) assert jitcode.constants_r == [s_gcref] Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py Fri Jun 4 19:24:22 2010 @@ -424,7 +424,7 @@ assert op1.opname == 'new_with_vtable' assert op1.args == [('sizedescr', S)] #assert heaptracker.descr2vtable(cpu, op1.args[0]) == vtable [type check] - vtable_int = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable)) + vtable_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable)) assert heaptracker.vtable2descr(cpu, vtable_int) == op1.args[0] def test_malloc_new_with_destructor(): Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py Fri Jun 4 19:24:22 2010 @@ -734,7 +734,7 @@ @arguments("self", "i", "L", "pc", returns="L") def bhimpl_goto_if_exception_mismatch(self, vtable, target, pc): - adr = llmemory.cast_int_to_adr(vtable) + adr = heaptracker.int2adr(vtable) bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) real_instance = self.exception_last_value assert real_instance @@ -748,7 +748,7 @@ real_instance = self.exception_last_value assert real_instance adr = llmemory.cast_ptr_to_adr(real_instance.typeptr) - return llmemory.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) @arguments("self", returns="r") def bhimpl_last_exc_value(self): @@ -807,7 +807,7 @@ def get_portal_runner(self): metainterp_sd = self.builder.metainterp_sd fnptr = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) - fnptr = llmemory.cast_adr_to_int(fnptr) + fnptr = heaptracker.adr2int(fnptr) calldescr = metainterp_sd.portal_code.calldescr return fnptr, calldescr @@ -1120,10 +1120,6 @@ def bhimpl_guard_class(cpu, struct): return cpu.bh_classof(struct) - @arguments("cpu", "r", returns="i") - def bhimpl_cast_ptr_to_int(cpu, p): - return cpu.bh_cast_ptr_to_int(p) - @arguments("cpu", "i", returns="r") def bhimpl_newstr(cpu, length): return cpu.bh_newstr(length) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py Fri Jun 4 19:24:22 2010 @@ -9,6 +9,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -202,7 +203,7 @@ kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): - intval = llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) @@ -265,7 +266,7 @@ return self.value def getaddr(self): - return llmemory.cast_int_to_adr(self.value) + return heaptracker.int2adr(self.value) def _get_hash_(self): return make_hashable_int(self.value) @@ -506,7 +507,7 @@ return self.value def getaddr(self): - return llmemory.cast_int_to_adr(self.value) + return heaptracker.int2adr(self.value) def _get_hash_(self): return make_hashable_int(self.value) @@ -675,8 +676,8 @@ def make_hashable_int(i): if not we_are_translated() and isinstance(i, llmemory.AddressAsInt): # Warning: such a hash changes at the time of translation - adr = llmemory.cast_int_to_adr(i) - return lltype.cast_ptr_to_int(adr.ptr) + adr = heaptracker.int2adr(i) + return llmemory.cast_adr_to_int(adr, "emulated") return i # ____________________________________________________________ Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/logger.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/logger.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/logger.py Fri Jun 4 19:24:22 2010 @@ -2,7 +2,7 @@ from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print from pypy.rlib.objectmodel import we_are_translated -from pypy.rpython.lltypesystem import llmemory, rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, \ BoxInt, ConstFloat, BoxFloat, AbstractFailDescr @@ -108,7 +108,7 @@ def int_could_be_an_address(x): if we_are_translated(): - x = rffi.get_real_int(x) + x = rffi.cast(lltype.Signed, x) # force it return not (-32768 <= x <= 32767) else: return isinstance(x, llmemory.AddressAsInt) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Fri Jun 4 19:24:22 2010 @@ -20,6 +20,7 @@ from pypy.rlib.objectmodel import specialize from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -194,8 +195,8 @@ ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert', - 'cast_ptr_to_int', 'cast_float_to_int', - 'cast_int_to_float', 'float_neg', 'float_abs', + 'cast_float_to_int', 'cast_int_to_float', + 'float_neg', 'float_abs', ]: exec py.code.Source(''' @arguments("box") @@ -334,7 +335,6 @@ @arguments("descr") def opimpl_new_with_vtable(self, sizedescr): - from pypy.jit.codewriter import heaptracker cpu = self.metainterp.cpu cls = heaptracker.descr2vtable(cpu, sizedescr) return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls)) @@ -672,7 +672,7 @@ self.verify_green_args(greenboxes) # k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) - funcbox = ConstInt(llmemory.cast_adr_to_int(k)) + funcbox = ConstInt(heaptracker.adr2int(k)) return self.do_residual_call(funcbox, portal_code.calldescr, allboxes, assembler_call_token=token) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/resoperation.py Fri Jun 4 19:24:22 2010 @@ -138,7 +138,6 @@ #'OOSEND_PURE', # ootype operation 'CALL_PURE', # - 'CAST_PTR_TO_INT/1', 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/oparser.py Fri Jun 4 19:24:22 2010 @@ -8,6 +8,7 @@ LoopToken from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.typesystem import llhelper +from pypy.jit.codewriter.heaptracker import adr2int from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llstr @@ -74,8 +75,7 @@ return ConstPtr(obj) else: assert typ == 'class' - return ConstInt(llmemory.cast_adr_to_int( - llmemory.cast_ptr_to_adr(obj))) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(obj))) else: if typ == 'ptr': return ConstObj(obj) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py Fri Jun 4 19:24:22 2010 @@ -1548,6 +1548,7 @@ assert self.interp_operations(f, [0, 1]) == expected def test_casts(self): + py.test.skip("xxx fix or kill") if not self.basic: py.test.skip("test written in a style that " "means it's frontend only") Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizefindnode.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizefindnode.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_optimizefindnode.py Fri Jun 4 19:24:22 2010 @@ -17,7 +17,7 @@ from pypy.jit.metainterp.specnode import VirtualStructSpecNode from pypy.jit.metainterp.specnode import ConstantSpecNode from pypy.jit.codewriter.effectinfo import EffectInfo -from pypy.jit.codewriter.heaptracker import register_known_gctype +from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int from pypy.jit.metainterp.test.oparser import parse def test_sort_descrs(): @@ -219,9 +219,7 @@ # def constclass(cls_vtable): if self.type_system == 'lltype': - return ConstInt( - llmemory.cast_adr_to_int( - llmemory.cast_ptr_to_adr(cls_vtable))) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable))) else: return ConstObj(ootype.cast_to_object(cls_vtable)) def constant(value): Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_resume.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_resume.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_resume.py Fri Jun 4 19:24:22 2010 @@ -7,6 +7,7 @@ from pypy.jit.metainterp.history import ConstPtr, ConstFloat from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin from pypy.jit.metainterp import executor +from pypy.jit.codewriter import heaptracker class Storage: rd_frame_info_list = None @@ -444,8 +445,8 @@ pass fakeoptimizer = FakeOptimizer_VirtualValue() -def ConstAddr(addr, cpu=None): # compatibility - return ConstInt(llmemory.cast_adr_to_int(addr)) +def ConstAddr(addr, cpu): # compatibility + return ConstInt(heaptracker.adr2int(addr)) def virtual_value(keybox, value, next): vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr, Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py Fri Jun 4 19:24:22 2010 @@ -4,6 +4,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import r_dict def deref(T): @@ -74,7 +75,7 @@ def cls_of_box(self, box): obj = box.getref(lltype.Ptr(rclass.OBJECT)) cls = llmemory.cast_ptr_to_adr(obj.typeptr) - return history.ConstInt(llmemory.cast_adr_to_int(cls)) + return history.ConstInt(heaptracker.adr2int(cls)) def instanceOf(self, instbox, clsbox): adr = clsbox.getaddr() @@ -119,7 +120,7 @@ def cast_vtable_to_hashable(self, cpu, ptr): adr = llmemory.cast_ptr_to_adr(ptr) - return llmemory.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) def cast_from_ref(self, TYPE, value): return lltype.cast_opaque_ptr(TYPE, value) Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualref.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualref.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualref.py Fri Jun 4 19:24:22 2010 @@ -1,6 +1,7 @@ from pypy.rpython.rmodel import inputconst, log from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker class VirtualRefInfo: @@ -20,7 +21,7 @@ 'jit_virtual_ref') # build some constants adr = llmemory.cast_ptr_to_adr(self.jit_virtual_ref_vtable) - adr = llmemory.cast_adr_to_int(adr) + adr = heaptracker.adr2int(adr) self.jit_virtual_ref_const_class = history.ConstInt(adr) fielddescrof = self.cpu.fielddescrof self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF, Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmstate.py Fri Jun 4 19:24:22 2010 @@ -12,7 +12,7 @@ from pypy.rlib.jit import BaseJitCell from pypy.rlib.debug import debug_start, debug_stop, debug_print from pypy.jit.metainterp import history -from pypy.jit.codewriter import support +from pypy.jit.codewriter import support, heaptracker # ____________________________________________________________ @@ -54,7 +54,7 @@ return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) - value = llmemory.cast_adr_to_int(adr) + value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Fri Jun 4 19:24:22 2010 @@ -1208,9 +1208,9 @@ S = lltype.Struct('S') p = lltype.malloc(S, flavor='raw') a = llmemory.cast_ptr_to_adr(p) - i = rffi.get_real_int(llmemory.cast_adr_to_int(a)) + i = llmemory.cast_adr_to_int(a, "forced") assert type(i) is int - assert i == rffi.get_real_int(llmemory.cast_adr_to_int(a)) + assert i == llmemory.cast_adr_to_int(a, "forced") lltype.free(p, flavor='raw') class TestPlatform(object): Modified: pypy/branch/blackhole-improvement/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/memory/test/test_lldict.py Fri Jun 4 19:24:22 2010 @@ -100,7 +100,7 @@ _TYPE = llmemory.Address def __init__(self, intval): self.intval = intval - def _cast_to_int(self): + def _cast_to_int(self, symbolic="?"): return self.intval def __repr__(self): return '' % (self.intval & (sys.maxint*2+1),) Modified: pypy/branch/blackhole-improvement/pypy/rpython/raddress.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/raddress.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/raddress.py Fri Jun 4 19:24:22 2010 @@ -57,9 +57,7 @@ get_ll_fasthash_function = get_ll_hash_function def ll_addrhash(addr1): - # we don't want to have an AddressAsInt instance in this case - from pypy.rpython.lltypesystem import rffi - return rffi.get_real_int(cast_adr_to_int(addr1)) + return cast_adr_to_int(addr1, "forced") address_repr = AddressRepr() From afa at codespeak.net Fri Jun 4 20:50:03 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 20:50:03 +0200 (CEST) Subject: [pypy-svn] r75118 - pypy/trunk/pypy/module/cpyext/test Message-ID: <20100604185003.BF5B5282B9E@codespeak.net> Author: afa Date: Fri Jun 4 20:50:01 2010 New Revision: 75118 Modified: pypy/trunk/pypy/module/cpyext/test/test_longobject.py Log: Fix test on 64bit platforms Modified: pypy/trunk/pypy/module/cpyext/test/test_longobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_longobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_longobject.py Fri Jun 4 20:50:01 2010 @@ -76,7 +76,11 @@ """ return PyLong_FromUnsignedLong((unsigned long)-1); """)]) - assert module.from_unsignedlong() == (1<<32) - 1 + import sys + if sys.maxint < 1<<32: + assert module.from_unsignedlong() == (1<<32) - 1 + else: + assert module.from_unsignedlong() == (1<<64) - 1 def test_fromlonglong(self): module = self.import_extension('foo', [ From afa at codespeak.net Fri Jun 4 20:55:45 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 20:55:45 +0200 (CEST) Subject: [pypy-svn] r75119 - pypy/trunk/pypy/module/cpyext/test Message-ID: <20100604185545.CA709282B9E@codespeak.net> Author: afa Date: Fri Jun 4 20:55:43 2010 New Revision: 75119 Modified: pypy/trunk/pypy/module/cpyext/test/test_longobject.py Log: Simplify test, thanks Alex Modified: pypy/trunk/pypy/module/cpyext/test/test_longobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_longobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_longobject.py Fri Jun 4 20:55:43 2010 @@ -77,10 +77,7 @@ return PyLong_FromUnsignedLong((unsigned long)-1); """)]) import sys - if sys.maxint < 1<<32: - assert module.from_unsignedlong() == (1<<32) - 1 - else: - assert module.from_unsignedlong() == (1<<64) - 1 + assert module.from_unsignedlong() == 2 * sys.maxint + 1 def test_fromlonglong(self): module = self.import_extension('foo', [ From afa at codespeak.net Fri Jun 4 22:12:28 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 22:12:28 +0200 (CEST) Subject: [pypy-svn] r75120 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100604201228.28B79282BF1@codespeak.net> Author: afa Date: Fri Jun 4 22:12:26 2010 New Revision: 75120 Modified: pypy/trunk/pypy/module/cpyext/sliceobject.py pypy/trunk/pypy/module/cpyext/test/test_sliceobject.py Log: PySlice_New() allows NULLs. Test and fix. Modified: pypy/trunk/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/sliceobject.py (original) +++ pypy/trunk/pypy/module/cpyext/sliceobject.py Fri Jun 4 22:12:26 2010 @@ -56,6 +56,12 @@ the same names. Any of the values may be NULL, in which case the None will be used for the corresponding attribute. Return NULL if the new object could not be allocated.""" + if w_start is None: + w_start = space.w_None + if w_stop is None: + w_stop = space.w_None + if w_step is None: + w_step = space.w_None return W_SliceObject(w_start, w_stop, w_step) @cpython_api([PySliceObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, Modified: pypy/trunk/pypy/module/cpyext/test/test_sliceobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_sliceobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_sliceobject.py Fri Jun 4 22:12:26 2010 @@ -43,3 +43,12 @@ ]) s = slice(10, 20, 30) assert module.clone(s) == s + + def test_nulls(self): + module = self.import_extension('foo', [ + ("nullslice", "METH_NOARGS", + """ + return PySlice_New(NULL, NULL, NULL); + """), + ]) + assert module.nullslice() == slice(None, None, None) From afa at codespeak.net Fri Jun 4 22:43:58 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 22:43:58 +0200 (CEST) Subject: [pypy-svn] r75121 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100604204358.7A6D1282BF2@codespeak.net> Author: afa Date: Fri Jun 4 22:43:56 2010 New Revision: 75121 Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Log: Implement the tp_str slot Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/slotdefs.py (original) +++ pypy/trunk/pypy/module/cpyext/slotdefs.py Fri Jun 4 22:43:56 2010 @@ -175,6 +175,10 @@ return space.call(w_self, w_args, w_kwds) @cpython_api([PyObject], PyObject, external=False) +def slot_tp_str(space, w_self): + return space.str(w_self) + + at cpython_api([PyObject], PyObject, external=False) def slot_nb_int(space, w_self): return space.int(w_self) Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Fri Jun 4 22:43:56 2010 @@ -289,3 +289,22 @@ def __call__(self, *args): return args assert module.tp_call(C(), ('x', 2)) == ('x', 2) + + def test_tp_str(self): + module = self.import_extension('foo', [ + ("tp_str", "METH_O", + ''' + if (!args->ob_type->tp_str) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + return args->ob_type->tp_str(args); + ''' + ) + ]) + class C: + def __str__(self): + return "text" + assert module.tp_str(C()) == "text" + From afa at codespeak.net Fri Jun 4 23:26:15 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 4 Jun 2010 23:26:15 +0200 (CEST) Subject: [pypy-svn] r75122 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100604212615.D6208282BF1@codespeak.net> Author: afa Date: Fri Jun 4 23:26:14 2010 New Revision: 75122 Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py pypy/trunk/pypy/module/cpyext/test/foo.c pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Log: implement wrap_descr_get, wrap_descr_set, wrap_descr_delete Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/slotdefs.py (original) +++ pypy/trunk/pypy/module/cpyext/slotdefs.py Fri Jun 4 23:26:14 2010 @@ -5,7 +5,8 @@ from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc, - ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc) + ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc, + descrgetfunc, descrsetfunc) from pypy.module.cpyext.pyobject import from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.state import State @@ -82,6 +83,44 @@ if rffi.cast(lltype.Signed, res) == -1: space.fromcache(State).check_and_raise_exception(always=True) +def wrap_descr_get(space, w_self, w_args, func): + func_target = rffi.cast(descrgetfunc, func) + args_w = space.fixedview(w_args) + if len(args_w) == 1: + w_obj, = args_w + w_type = None + elif len(args_w) == 2: + w_obj, w_type = args_w + else: + raise operationerrfmt( + space.w_TypeError, + "expected 1 or 2 arguments, got %d", len(args_w)) + if w_obj is space.w_None: + w_obj = None + if w_type is space.w_None: + w_type = None + if w_obj is None and w_type is None: + raise OperationError( + space.w_TypeError, + space.wrap("__get__(None, None) is invalid")) + return generic_cpy_call(space, func_target, w_self, w_obj, w_type) + +def wrap_descr_set(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 2) + w_obj, w_value = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, w_value) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_descr_delete(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 1) + w_obj, = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, None) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + def wrap_call(space, w_self, w_args, func, w_kwds): func_target = rffi.cast(ternaryfunc, func) return generic_cpy_call(space, func_target, w_self, w_args, w_kwds) Modified: pypy/trunk/pypy/module/cpyext/test/foo.c ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/foo.c (original) +++ pypy/trunk/pypy/module/cpyext/test/foo.c Fri Jun 4 23:26:14 2010 @@ -483,6 +483,90 @@ 0 /*tp_weaklist*/ }; +PyObject * prop_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + if (obj == NULL) + obj = Py_None; + if (type == NULL) + type = Py_None; + + return PyTuple_Pack(3, self, obj, type); +} + +int prop_descr_set(PyObject *self, PyObject *obj, PyObject *value) +{ + int res; + if (value != NULL) { + PyObject *result = PyTuple_Pack(2, self, value); + res = PyObject_SetAttrString(obj, "y", result); + Py_DECREF(result); + } + else { + res = PyObject_SetAttrString(obj, "z", self); + } + return res; +} + + +PyTypeObject SimplePropertyType = { + PyObject_HEAD_INIT(NULL) + 0, + "foo.Property", + sizeof(PyObject), + 0, + 0, /*tp_dealloc*/ + 0, /*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*/ + + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + 0, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + prop_descr_get, /*tp_descr_get*/ + prop_descr_set, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + 0, /*tp_init*/ + 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ + 0, /*tp_new*/ + 0, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + /* Initialize this module. */ @@ -506,6 +590,8 @@ return; if (PyType_Ready(&InitErrType) < 0) return; + if (PyType_Ready(&SimplePropertyType) < 0) + return; m = Py_InitModule("foo", foo_functions); if (m == NULL) return; @@ -522,4 +608,6 @@ return; if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0) return; + if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0) + return; } Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Fri Jun 4 23:26:14 2010 @@ -192,6 +192,20 @@ assert d[cmpr] == 72 assert d[3] == 72 + def test_descriptor(self): + module = self.import_module("foo") + prop = module.Property() + class C(object): + x = prop + obj = C() + assert obj.x == (prop, obj, C) + assert C.x == (prop, None, C) + + obj.x = 2 + assert obj.y == (prop, 2) + del obj.x + assert obj.z == prop + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): From getxsick at codespeak.net Fri Jun 4 23:37:58 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 4 Jun 2010 23:37:58 +0200 (CEST) Subject: [pypy-svn] r75123 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100604213758.46EA5282BF1@codespeak.net> Author: getxsick Date: Fri Jun 4 23:37:56 2010 New Revision: 75123 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: support for non args (void) functions Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Fri Jun 4 23:37:56 2010 @@ -117,7 +117,7 @@ elif arg == 'ref': args.append(lltype.Signed) elif arg == 'void': - args.append(None) + break else: raise ValueError(arg) @@ -135,7 +135,7 @@ elif tp == 'ref': bargs.append(BoxPtr(value)) elif tp == 'void': - assert False #XXX + break inputargs = [self.bfuncaddr] + bargs oplist = [ResOperation(rop.CALL, inputargs, self.bres, Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Fri Jun 4 23:37:56 2010 @@ -32,10 +32,15 @@ if (c > max) max = c; return max; } + + int fvoid(void) + { + return 1; + } ''' )) - symbols = ['add_integers', 'add_floats', 'return_float', 'max3'] + symbols = ['add_integers', 'add_floats', 'return_float', 'max3', 'fvoid'] eci = ExternalCompilationInfo(export_symbols=symbols) return str(platform.compile([c_file], eci, 'x', standalone=False)) @@ -66,7 +71,7 @@ #res = lib.call('return_float', [1.5, 1.2], 'float') #assert 2.7 == res - def test_get_with_same_type(self): + def test_get(self): lib = jitffi.CDLL(self.lib_name) func = lib.get('add_integers', ['int', 'int'], 'int') @@ -84,9 +89,13 @@ def test_get_void(self): lib = jitffi.CDLL(self.lib_name) + py.test.raises(ValueError, lib.get, 'add_integers', ['void', 'int'], 'int') + func = lib.get('fvoid', ['void'], 'int') + assert 1 == func('void') + def test_undefined_func(self): lib = jitffi.CDLL(self.lib_name) # xxxfoo888baryyy - not existed function From benjamin at codespeak.net Fri Jun 4 23:47:45 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 4 Jun 2010 23:47:45 +0200 (CEST) Subject: [pypy-svn] r75124 - pypy/trunk/pypy/objspace/std Message-ID: <20100604214745.3FA82282BF1@codespeak.net> Author: benjamin Date: Fri Jun 4 23:47:43 2010 New Revision: 75124 Modified: pypy/trunk/pypy/objspace/std/formatting.py Log: remove unused function Modified: pypy/trunk/pypy/objspace/std/formatting.py ============================================================================== --- pypy/trunk/pypy/objspace/std/formatting.py (original) +++ pypy/trunk/pypy/objspace/std/formatting.py Fri Jun 4 23:47:43 2010 @@ -474,12 +474,6 @@ [_name[-1] for _name in dir(StringFormatter) if len(_name) == 5 and _name.startswith('fmt_')]) -def is_list_of_chars_or_unichars(ann, bk): - from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint - if not isinstance(ann.listdef.listitem.s_value, - (SomeChar, SomeUnicodeCodePoint)): - raise TypeError("Formatter should return as a result a list of chars or unichars, otherwise we miss important optimization") - def format(space, w_fmt, values_w, w_valuedict=None, do_unicode=False): "Entry point" if not do_unicode: From getxsick at codespeak.net Fri Jun 4 23:56:31 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 4 Jun 2010 23:56:31 +0200 (CEST) Subject: [pypy-svn] r75125 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100604215631.C7914282BF1@codespeak.net> Author: getxsick Date: Fri Jun 4 23:56:30 2010 New Revision: 75125 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: support for functions which return void Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Fri Jun 4 23:56:30 2010 @@ -2,7 +2,7 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.jit.backend.x86.runner import CPU from pypy.jit.metainterp.history import LoopToken, BasicFailDescr -from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr, NULLBOX from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.typesystem import deref @@ -97,8 +97,8 @@ self.bres = BoxPtr() res = lltype.Signed elif self.res_type == 'void': - self.bres = None - res = None + self.bres = NULLBOX + res = lltype.Void else: raise ValueError(self.res_type) Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Fri Jun 4 23:56:30 2010 @@ -37,10 +37,17 @@ { return 1; } + + void return_void(int a, int b) + { + int c; + c = a + b; + } ''' )) - symbols = ['add_integers', 'add_floats', 'return_float', 'max3', 'fvoid'] + symbols = ['add_integers', 'add_floats', 'return_float', + 'max3', 'fvoid', 'return_void'] eci = ExternalCompilationInfo(export_symbols=symbols) return str(platform.compile([c_file], eci, 'x', standalone=False)) @@ -96,6 +103,9 @@ func = lib.get('fvoid', ['void'], 'int') assert 1 == func('void') + func = lib.get('return_void', ['int', 'int'], 'void') + assert func(1, 2) is None + def test_undefined_func(self): lib = jitffi.CDLL(self.lib_name) # xxxfoo888baryyy - not existed function From getxsick at codespeak.net Sat Jun 5 00:05:50 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 5 Jun 2010 00:05:50 +0200 (CEST) Subject: [pypy-svn] r75126 - pypy/branch/fast-ctypes/pypy/rlib/test Message-ID: <20100604220550.A96CA282BF1@codespeak.net> Author: getxsick Date: Sat Jun 5 00:05:49 2010 New Revision: 75126 Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: more tests Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Sat Jun 5 00:05:49 2010 @@ -102,9 +102,12 @@ func = lib.get('fvoid', ['void'], 'int') assert 1 == func('void') + assert 1 == func() func = lib.get('return_void', ['int', 'int'], 'void') assert func(1, 2) is None + func = lib.get('return_void', ['int', 'int']) + assert func(1, 2) is None def test_undefined_func(self): lib = jitffi.CDLL(self.lib_name) From afa at codespeak.net Sat Jun 5 00:26:51 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 5 Jun 2010 00:26:51 +0200 (CEST) Subject: [pypy-svn] r75127 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100604222651.12523282BF1@codespeak.net> Author: afa Date: Sat Jun 5 00:26:50 2010 New Revision: 75127 Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py pypy/trunk/pypy/module/cpyext/typeobject.py Log: Small support for Py_TYPE(x)->tp_dict: it is a "dictproxy" of the (rpython) w_type.dict_w. Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Sat Jun 5 00:26:50 2010 @@ -206,6 +206,27 @@ del obj.x assert obj.z == prop + def test_tp_dict(self): + foo = self.import_module("foo") + module = self.import_extension('test', [ + ("read_tp_dict", "METH_O", + ''' + PyObject *method; + if (!args->ob_type->tp_dict) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + method = PyDict_GetItemString( + args->ob_type->tp_dict, "copy"); + Py_INCREF(method); + return method; + ''' + ) + ]) + obj = foo.new() + assert module.read_tp_dict(obj) == foo.fooType.copy + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): @@ -304,7 +325,7 @@ return args assert module.tp_call(C(), ('x', 2)) == ('x', 2) - def test_tp_str(self): + def test_tp_str(self): module = self.import_extension('foo', [ ("tp_str", "METH_O", ''' @@ -321,4 +342,3 @@ def __str__(self): return "text" assert module.tp_str(C()) == "text" - Modified: pypy/trunk/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/typeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/typeobject.py Sat Jun 5 00:26:50 2010 @@ -382,6 +382,7 @@ Py_DecRef(space, obj_pto.c_tp_bases) Py_DecRef(space, obj_pto.c_tp_mro) Py_DecRef(space, obj_pto.c_tp_cache) # let's do it like cpython + Py_DecRef(space, obj_pto.c_tp_dict) if obj_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: if obj_pto.c_tp_as_buffer: lltype.free(obj_pto.c_tp_as_buffer, flavor='raw') @@ -543,8 +544,6 @@ """ Sets up tp_bases, necessary before creating the interpreter type. """ - pto.c_tp_dict = lltype.nullptr(PyObject.TO) # not supported - base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: @@ -575,6 +574,10 @@ PyObject_GenericSetAttr.api_func.functype, PyObject_GenericSetAttr.api_func.get_wrapper(space)) + if w_obj.is_cpytype(): + Py_DecRef(space, pto.c_tp_dict) + pto.c_tp_dict = make_ref(space, w_obj.getdict()) + @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. From getxsick at codespeak.net Sat Jun 5 18:46:53 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 5 Jun 2010 18:46:53 +0200 (CEST) Subject: [pypy-svn] r75129 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100605164653.2C982282BEC@codespeak.net> Author: getxsick Date: Sat Jun 5 18:46:51 2010 New Revision: 75129 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: there is no more 'void' as a function argument. use empty list of args instead Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Sat Jun 5 18:46:51 2010 @@ -80,13 +80,11 @@ class _Get(object): def __init__(self, cpu, lib, func, args_type, res_type='void'): assert isinstance(args_type, list) - if 'void' in args_type and len(args_type) > 1: - raise ValueError("'void' must be the only parameter") self.args_type = args_type self.res_type = res_type self.cpu = cpu self.lib = lib - # XXX add 'void' handling + if self.res_type == 'int': self.bres = BoxInt() res = lltype.Signed @@ -116,8 +114,6 @@ args.append(lltype.Float) elif arg == 'ref': args.append(lltype.Signed) - elif arg == 'void': - break else: raise ValueError(arg) @@ -134,8 +130,6 @@ bargs.append(BoxFloat(value)) elif tp == 'ref': bargs.append(BoxPtr(value)) - elif tp == 'void': - break inputargs = [self.bfuncaddr] + bargs oplist = [ResOperation(rop.CALL, inputargs, self.bres, Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Sat Jun 5 18:46:51 2010 @@ -1,6 +1,7 @@ from pypy.rlib import jitffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform +from pypy.rpython.lltypesystem import rffi, lltype import py @@ -97,11 +98,7 @@ def test_get_void(self): lib = jitffi.CDLL(self.lib_name) - py.test.raises(ValueError, lib.get, - 'add_integers', ['void', 'int'], 'int') - - func = lib.get('fvoid', ['void'], 'int') - assert 1 == func('void') + func = lib.get('fvoid', [], 'int') assert 1 == func() func = lib.get('return_void', ['int', 'int'], 'void') From getxsick at codespeak.net Sat Jun 5 19:01:12 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 5 Jun 2010 19:01:12 +0200 (CEST) Subject: [pypy-svn] r75130 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100605170112.3F658282BEC@codespeak.net> Author: getxsick Date: Sat Jun 5 19:01:10 2010 New Revision: 75130 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: kill CDLL.call(), use CDLL.get() instead Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Sat Jun 5 19:01:10 2010 @@ -16,64 +16,6 @@ self.name = name self.cpu = CPU(None, None) - def call(self, func, func_args, res_type='void'): - # only integers are supported for now - assert isinstance(func_args, list) - - if res_type == 'int': - bres = BoxInt() - elif res_type == 'float': - bres = BoxFloat() - elif res_type == 'ref': - bres = BoxPtr() - elif res_type == 'void': - bres = None - else: - raise ValueError(res_type) - - try: - addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func)) - except KeyError: - raise ValueError("Cannot find symbol %s", func) - bfuncaddr = BoxInt(addr) - - args_type = [ lltype.Signed for i in func_args ] - FPTR = lltype.Ptr(lltype.FuncType(args_type, lltype.Signed)) - FUNC = deref(FPTR) - calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) - - bargs = [ BoxInt(x) for x in func_args ] - inputargs = [bfuncaddr] + bargs - - oplist = [ResOperation(rop.CALL, inputargs, bres, descr=calldescr), - ResOperation(rop.FINISH, [bres], None, - descr=BasicFailDescr(0))] - looptoken = LoopToken() - self.cpu.compile_loop(inputargs, oplist, looptoken) - - i = 0 - for box in inputargs: - self.cpu.set_future_value_int(i, box.getint()) - i += 1 - - res = self.cpu.execute_token(looptoken) - if res is oplist[-1].descr: - self.guard_failed = False - else: - self.guard_failed = True - - if res_type == 'int': - r = BoxInt(self.cpu.get_latest_value_int(0)).getint() - elif res_type == 'float': - r = BoxFloat(self.cpu.get_latest_value_float(0)).getfloat() - elif res_type == 'ref': - r = BoxPtr(self.cpu.get_latest_value_ref(0)).getref() - elif res_type == 'void': - r = None - else: - raise ValueError(res_type) - return r - def get(self, func, args_type, res_type='void'): return _Get(self.cpu, self.lib, func, args_type, res_type) Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Sat Jun 5 19:01:10 2010 @@ -59,26 +59,6 @@ def test_missing_lib(self): py.test.raises(OSError, jitffi.CDLL, 'xxxfoo888baryyy') - def test_call(self): - lib = jitffi.CDLL(self.lib_name) - - res = lib.call('add_integers', [1, 2], 'int') - assert 3 == res - assert isinstance(res, int) - res = lib.call('add_integers', [-1, 2], 'int') - assert 1 == res - res = lib.call('add_integers', [0, 0], 'int') - assert 0 == res - - res = lib.call('max3', [2, 8, 3], 'int') - assert 8 == res - - res = lib.call('return_float', [1, 2], 'float') - assert 3.0 == res - assert isinstance(res, float) - #res = lib.call('return_float', [1.5, 1.2], 'float') - #assert 2.7 == res - def test_get(self): lib = jitffi.CDLL(self.lib_name) From fijal at codespeak.net Sat Jun 5 19:02:11 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jun 2010 19:02:11 +0200 (CEST) Subject: [pypy-svn] r75131 - pypy/branch/unfreeze-encodings/pypy/module/sys Message-ID: <20100605170211.D64E6282BEC@codespeak.net> Author: fijal Date: Sat Jun 5 19:02:10 2010 New Revision: 75131 Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Log: Fix NameError Modified: pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/unfreeze-encodings/pypy/module/sys/interp_encoding.py Sat Jun 5 19:02:10 2010 @@ -1,5 +1,6 @@ import sys from pypy.rlib import rlocale +from pypy.rlib.objectmodel import we_are_translated def getdefaultencoding(space): """Return the current default string encoding used by the Unicode From fijal at codespeak.net Sat Jun 5 19:24:16 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jun 2010 19:24:16 +0200 (CEST) Subject: [pypy-svn] r75132 - pypy/branch/unfreeze-encodings/pypy/objspace/std Message-ID: <20100605172416.DDA38282BEC@codespeak.net> Author: fijal Date: Sat Jun 5 19:24:15 2010 New Revision: 75132 Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Log: An attempt (?) to fix translation Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Sat Jun 5 19:24:15 2010 @@ -201,11 +201,11 @@ except UnicodeEncodeError, uee: raise OperationError(space.w_UnicodeEncodeError, space.newtuple([ - space.wrap(uee.encoding), - space.wrap(uee.object), - space.wrap(uee.start), - space.wrap(uee.end), - space.wrap(uee.reason)])) + space.wrap(uee.args[0]), + space.wrap(uee.args[1]), + space.wrap(uee.args[2]), + space.wrap(uee.args[3]), + space.wrap(uee.args[4])])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -234,9 +234,9 @@ return space.wrap(str_decode_utf_8(s, len(s), None)[0]) except UnicodeDecodeError, ude: raise OperationError(space.w_UnicodeDecodeError, space.newtuple( - [space.wrap(ude.encoding), space.wrap(ude.object), - space.wrap(ude.start), space.wrap(ude.end), - space.wrap(ude.reason)])) + [space.wrap(ude.args[0]), space.wrap(ude.args[1]), + space.wrap(ude.args[2]), space.wrap(ude.args[3]), + space.wrap(ude.args[4])])) w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: From getxsick at codespeak.net Sat Jun 5 19:47:50 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 5 Jun 2010 19:47:50 +0200 (CEST) Subject: [pypy-svn] r75133 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100605174750.37F9D36C374@codespeak.net> Author: getxsick Date: Sat Jun 5 19:47:48 2010 New Revision: 75133 Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: rename __call__() to call() Modified: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py Sat Jun 5 19:47:48 2010 @@ -63,7 +63,7 @@ FUNC = deref(FPTR) self.calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) - def __call__(self, *func_args): + def call(self, *func_args): bargs = [] for tp, value in zip(self.args_type, func_args): if tp == 'int': Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Sat Jun 5 19:47:48 2010 @@ -63,28 +63,28 @@ lib = jitffi.CDLL(self.lib_name) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 3 == func(1,2) + assert 3 == func.call(1,2) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 1 == func(-1,2) + assert 1 == func.call(-1,2) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 0 == func(0,0) + assert 0 == func.call(0,0) func = lib.get('max3', ['int', 'int', 'int'], 'int') - assert 8 == func(2, 8, 3) + assert 8 == func.call(2, 8, 3) func = lib.get('add_floats', ['float', 'float'], 'float') - assert 2.7 == func(1.2, 1.5) + assert 2.7 == func.call(1.2, 1.5) def test_get_void(self): lib = jitffi.CDLL(self.lib_name) func = lib.get('fvoid', [], 'int') - assert 1 == func() + assert 1 == func.call() func = lib.get('return_void', ['int', 'int'], 'void') - assert func(1, 2) is None + assert func.call(1, 2) is None func = lib.get('return_void', ['int', 'int']) - assert func(1, 2) is None + assert func.call(1, 2) is None def test_undefined_func(self): lib = jitffi.CDLL(self.lib_name) From fijal at codespeak.net Sat Jun 5 23:12:38 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jun 2010 23:12:38 +0200 (CEST) Subject: [pypy-svn] r75134 - pypy/branch/unfreeze-encodings/pypy/objspace/std Message-ID: <20100605211238.1B64A282B90@codespeak.net> Author: fijal Date: Sat Jun 5 23:12:36 2010 New Revision: 75134 Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Log: Revert previous checkin, will fix otherwise Modified: pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/unfreeze-encodings/pypy/objspace/std/unicodetype.py Sat Jun 5 23:12:36 2010 @@ -201,11 +201,11 @@ except UnicodeEncodeError, uee: raise OperationError(space.w_UnicodeEncodeError, space.newtuple([ - space.wrap(uee.args[0]), - space.wrap(uee.args[1]), - space.wrap(uee.args[2]), - space.wrap(uee.args[3]), - space.wrap(uee.args[4])])) + space.wrap(uee.encoding), + space.wrap(uee.object), + space.wrap(uee.start), + space.wrap(uee.end), + space.wrap(uee.reason)])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -234,9 +234,9 @@ return space.wrap(str_decode_utf_8(s, len(s), None)[0]) except UnicodeDecodeError, ude: raise OperationError(space.w_UnicodeDecodeError, space.newtuple( - [space.wrap(ude.args[0]), space.wrap(ude.args[1]), - space.wrap(ude.args[2]), space.wrap(ude.args[3]), - space.wrap(ude.args[4])])) + [space.wrap(ude.encoding), space.wrap(ude.object), + space.wrap(ude.start), space.wrap(ude.end), + space.wrap(ude.reason)])) w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: From fijal at codespeak.net Sat Jun 5 23:40:13 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jun 2010 23:40:13 +0200 (CEST) Subject: [pypy-svn] r75135 - in pypy/branch/unfreeze-encodings/pypy/annotation: . test Message-ID: <20100605214013.477AA282B90@codespeak.net> Author: fijal Date: Sat Jun 5 23:40:11 2010 New Revision: 75135 Modified: pypy/branch/unfreeze-encodings/pypy/annotation/classdef.py pypy/branch/unfreeze-encodings/pypy/annotation/test/test_annrpython.py Log: Make attributes work Modified: pypy/branch/unfreeze-encodings/pypy/annotation/classdef.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/annotation/classdef.py (original) +++ pypy/branch/unfreeze-encodings/pypy/annotation/classdef.py Sat Jun 5 23:40:11 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString + SomeString, SomeUnicodeString from pypy.annotation import description @@ -439,6 +439,16 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, + UnicodeDecodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeString(), + 'encoding': SomeString(), + 'reason': SomeString()}, + UnicodeEncodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeUnicodeString(), + 'encoding': SomeString(), + 'reason': SomeString()} } try: Modified: pypy/branch/unfreeze-encodings/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/unfreeze-encodings/pypy/annotation/test/test_annrpython.py Sat Jun 5 23:40:11 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_unicode_decode_error(self): + def f(): + try: + raise UnicodeDecodeError("x", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + return ude.end + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInteger) + def g(n): return [0,1,2,n] From fijal at codespeak.net Sat Jun 5 23:43:54 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jun 2010 23:43:54 +0200 (CEST) Subject: [pypy-svn] r75136 - pypy/branch/unfreeze-encodings/pypy/annotation Message-ID: <20100605214354.E5FD8282B90@codespeak.net> Author: fijal Date: Sat Jun 5 23:43:52 2010 New Revision: 75136 Modified: pypy/branch/unfreeze-encodings/pypy/annotation/binaryop.py Log: Fix typo Modified: pypy/branch/unfreeze-encodings/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/annotation/binaryop.py (original) +++ pypy/branch/unfreeze-encodings/pypy/annotation/binaryop.py Sat Jun 5 23:43:52 2010 @@ -442,7 +442,7 @@ return SomeUnicodeString() class __extend__(pairtype(SomeString, SomeUnicodeString), - pairtype(SomeString, SomeUnicodeString)): + pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") From fijal at codespeak.net Sun Jun 6 00:19:35 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 00:19:35 +0200 (CEST) Subject: [pypy-svn] r75137 - in pypy/branch/unfreeze-encodings/pypy/rpython: . test Message-ID: <20100605221935.9F4B9282B90@codespeak.net> Author: fijal Date: Sun Jun 6 00:19:33 2010 New Revision: 75137 Modified: pypy/branch/unfreeze-encodings/pypy/rpython/rbuiltin.py pypy/branch/unfreeze-encodings/pypy/rpython/test/test_rbuiltin.py Log: Make Unicode[Encode|Decode]Error understandable on RPython level Modified: pypy/branch/unfreeze-encodings/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/unfreeze-encodings/pypy/rpython/rbuiltin.py Sun Jun 6 00:19:33 2010 @@ -270,6 +270,37 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) +def rtype_UnicodeDecodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeDecodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + TPS = [hop.args_r[0], r_str, r_str, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + +def rtype_UnicodeEncodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeEncodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + r_unicode = hop.rtyper.type_system.rstr.unicode_repr + TPS = [hop.args_r[0], r_str, r_unicode, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + def rtype_WindowsError__init__(hop): if hop.nb_args == 2: raise TyperError("WindowsError() should not be called with " @@ -329,6 +360,8 @@ BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( rtype_OSError__init__) +BUILTIN_TYPER[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = rtype_UnicodeDecodeError_init +BUILTIN_TYPER[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = rtype_UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/unfreeze-encodings/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/unfreeze-encodings/pypy/rpython/test/test_rbuiltin.py Sun Jun 6 00:19:33 2010 @@ -496,6 +496,35 @@ res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy()) assert res == 123 + def test_unicode_errors(self): + def f(): + try: + raise UnicodeDecodeError("xx", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == "x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + + def f(): + try: + raise UnicodeEncodeError("xx", u"x", 0, 1, "reason") + except UnicodeEncodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == u"x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): From fijal at codespeak.net Sun Jun 6 00:31:00 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 00:31:00 +0200 (CEST) Subject: [pypy-svn] r75138 - pypy/branch/unfreeze-encodings/pypy/annotation Message-ID: <20100605223100.1066A282B90@codespeak.net> Author: fijal Date: Sun Jun 6 00:30:59 2010 New Revision: 75138 Modified: pypy/branch/unfreeze-encodings/pypy/annotation/builtin.py Log: missing checkin Modified: pypy/branch/unfreeze-encodings/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/annotation/builtin.py (original) +++ pypy/branch/unfreeze-encodings/pypy/annotation/builtin.py Sun Jun 6 00:30:59 2010 @@ -272,6 +272,12 @@ def OSError_init(s_self, *args): pass +def UnicodeDecodeError_init(s_self, *args): + pass + +def UnicodeEncodeError_init(s_self, *args): + pass + def WindowsError_init(s_self, *args): pass @@ -390,6 +396,8 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) +BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init +BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError From dan at codespeak.net Sun Jun 6 00:50:15 2010 From: dan at codespeak.net (dan at codespeak.net) Date: Sun, 6 Jun 2010 00:50:15 +0200 (CEST) Subject: [pypy-svn] r75139 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100605225015.D9B3D282BEF@codespeak.net> Author: dan Date: Sun Jun 6 00:50:14 2010 New Revision: 75139 Modified: pypy/trunk/pypy/module/cpyext/sequence.py pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_sequence.py Log: Added PySequence_Repeat() along with the relevant tests, and fixed test_sequence. Modified: pypy/trunk/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/sequence.py (original) +++ pypy/trunk/pypy/module/cpyext/sequence.py Sun Jun 6 00:50:14 2010 @@ -6,6 +6,14 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.objspace.std import listobject, tupleobject + at cpython_api([PyObject, Py_ssize_t], PyObject) +def PySequence_Repeat(space, w_obj, count): + """Return the result of repeating sequence object o count times, or NULL on + failure. This is the equivalent of the Python expression o * count. + + This function used an int type for count. This might require + changes in your code for properly supporting 64-bit systems.""" + return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PySequence_Check(space, w_obj): Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Sun Jun 6 00:50:14 2010 @@ -2363,9 +2363,7 @@ @cpython_api([PyObject], PyObject) def PyObject_Dir(space, o): - """This is equivalent to the Python expression dir(o), returning a (possibly - empty) list of strings appropriate for the object argument, or NULL if there - was an error. If the argument is NULL, this is like the Python dir(), + """This is equivalent to the Python expression dir(o), returning a (possibly empty) list of strings appropriate for the object argument, or NULL if there was an error. If the argument is NULL, this is like the Python dir(), returning the names of the current locals; in this case, if no execution frame is active then NULL is returned but PyErr_Occurred() will return false.""" raise NotImplementedError @@ -2403,15 +2401,6 @@ func.""" raise NotImplementedError - at cpython_api([PyObject, Py_ssize_t], PyObject) -def PySequence_Repeat(space, o, count): - """Return the result of repeating sequence object o count times, or NULL on - failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject], PyObject) def PySequence_InPlaceConcat(space, o1, o2): """Return the concatenation of o1 and o2 on success, and NULL on failure. Modified: pypy/trunk/pypy/module/cpyext/test/test_sequence.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_sequence.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_sequence.py Sun Jun 6 00:50:14 2010 @@ -8,7 +8,7 @@ def test_sequence(self, space, api): w_t = space.wrap((1, 2, 3, 4)) assert api.PySequence_Fast(w_t, "message") is w_t - w_l = space.wrap((1, 2, 3, 4)) + w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l assert space.int_w(api.PySequence_Fast_GET_ITEM(w_l, 1)) == 2 @@ -23,6 +23,15 @@ assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + def test_repeat(self, space, api): + def test(seq, count): + w_seq = space.wrap(seq) + w_repeated = api.PySequence_Repeat(w_seq, count) + assert space.eq_w(w_repeated, space.wrap(seq * count)) + + test((1, 2, 3, 4), 3) + test([1, 2, 3, 4], 3) + def test_concat(self, space, api): w_t1 = space.wrap(range(4)) w_t2 = space.wrap(range(4, 8)) From fijal at codespeak.net Sun Jun 6 00:55:05 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 00:55:05 +0200 (CEST) Subject: [pypy-svn] r75140 - pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem Message-ID: <20100605225505.090DF282BEF@codespeak.net> Author: fijal Date: Sun Jun 6 00:55:04 2010 New Revision: 75140 Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Log: raise more precise UnicodeDecodeError Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Sun Jun 6 00:55:04 2010 @@ -296,7 +296,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError + raise UnicodeDecodeError("ascii", str, 0, lgt, "ascii codec can't encode %d" % str.chars[i]) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' From fijal at codespeak.net Sun Jun 6 01:14:47 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 01:14:47 +0200 (CEST) Subject: [pypy-svn] r75141 - pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem Message-ID: <20100605231447.BD223282BEF@codespeak.net> Author: fijal Date: Sun Jun 6 01:14:46 2010 New Revision: 75141 Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Log: *Ekhem* Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Sun Jun 6 01:14:46 2010 @@ -296,7 +296,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError("ascii", str, 0, lgt, "ascii codec can't encode %d" % str.chars[i]) + raise UnicodeDecodeError("ascii", str, 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' From fijal at codespeak.net Sun Jun 6 01:42:22 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 01:42:22 +0200 (CEST) Subject: [pypy-svn] r75142 - pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem Message-ID: <20100605234222.8B725282BEF@codespeak.net> Author: fijal Date: Sun Jun 6 01:42:20 2010 New Revision: 75142 Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Log: Another attempt to fix translation Modified: pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/unfreeze-encodings/pypy/rpython/lltypesystem/rstr.py Sun Jun 6 01:42:20 2010 @@ -18,6 +18,7 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -296,7 +297,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError("ascii", str, 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) + raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' From benjamin at codespeak.net Sun Jun 6 15:28:16 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 6 Jun 2010 15:28:16 +0200 (CEST) Subject: [pypy-svn] r75143 - in pypy/branch/fast-forward/pypy: module/_locale rlib Message-ID: <20100606132816.B3027282BF3@codespeak.net> Author: benjamin Date: Sun Jun 6 15:28:14 2010 New Revision: 75143 Modified: pypy/branch/fast-forward/pypy/module/_locale/interp_locale.py pypy/branch/fast-forward/pypy/rlib/rlocale.py Log: localeconv should be in rlocale Modified: pypy/branch/fast-forward/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_locale/interp_locale.py (original) +++ pypy/branch/fast-forward/pypy/module/_locale/interp_locale.py Sun Jun 6 15:28:14 2010 @@ -65,9 +65,6 @@ setlocale.unwrap_spec = [ObjSpace, int, W_Root] -_lconv = lltype.Ptr(rlocale.cConfig.lconv) -_localeconv = rlocale.external('localeconv', [], _lconv) - def _w_copy_grouping(space, text): groups = [ space.wrap(ord(group)) for group in text ] if groups: @@ -76,7 +73,7 @@ def localeconv(space): "() -> dict. Returns numeric and monetary locale-specific parameters." - lp = _localeconv() + lp = rlocale.localeconv() # Numeric information w_result = space.newdict() Modified: pypy/branch/fast-forward/pypy/rlib/rlocale.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rlocale.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rlocale.py Sun Jun 6 15:28:14 2010 @@ -149,6 +149,9 @@ calling_conv=calling_conv, sandboxsafe=True) +_lconv = lltype.Ptr(cConfig.lconv) +localeconv = external('localeconv', [], _lconv) + _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP) def setlocale(category, locale): From benjamin at codespeak.net Sun Jun 6 17:19:45 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 6 Jun 2010 17:19:45 +0200 (CEST) Subject: [pypy-svn] r75144 - pypy/branch/fast-forward/lib-python Message-ID: <20100606151945.A8904282BF6@codespeak.net> Author: benjamin Date: Sun Jun 6 17:19:43 2010 New Revision: 75144 Modified: pypy/branch/fast-forward/lib-python/ (props changed) Log: switch to public svn lib From hpk at codespeak.net Sun Jun 6 17:32:24 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 6 Jun 2010 17:32:24 +0200 (CEST) Subject: [pypy-svn] r75145 - in pypy/trunk/pypy/tool/pytest: . test Message-ID: <20100606153224.23BC8282BF6@codespeak.net> Author: hpk Date: Sun Jun 6 17:32:22 2010 New Revision: 75145 Modified: pypy/trunk/pypy/tool/pytest/appsupport.py pypy/trunk/pypy/tool/pytest/test/test_appsupport.py Log: fix the pypy/py.test customized AppExceptionInfo: only try matching "space.w_NAME" exceptions for interplevel builtin exceptions Modified: pypy/trunk/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/trunk/pypy/tool/pytest/appsupport.py (original) +++ pypy/trunk/pypy/tool/pytest/appsupport.py Sun Jun 6 17:32:22 2010 @@ -86,11 +86,18 @@ if debug_excs: self._excinfo = debug_excs[0] + def __repr__(self): + return "" % self.operr.errorstr(self.space) + def exconly(self, tryshort=True): return '(application-level) ' + self.operr.errorstr(self.space) def errisinstance(self, exc): clsname = exc.__name__ + # we can only check for builtin exceptions + # as there is no canonical applevel one for custom interplevel ones + if exc.__module__ != "exceptions": + return False try: w_exc = getattr(self.space, 'w_' + clsname) except KeyboardInterrupt: Modified: pypy/trunk/pypy/tool/pytest/test/test_appsupport.py ============================================================================== --- pypy/trunk/pypy/tool/pytest/test/test_appsupport.py (original) +++ pypy/trunk/pypy/tool/pytest/test/test_appsupport.py Sun Jun 6 17:32:22 2010 @@ -113,6 +113,19 @@ "*E*application-level*NameError*x*not defined", ]) +def test_applevel_raise_keyerror(testdir): + setpypyconftest(testdir) + p = testdir.makepyfile(""" + def app_test_raises(): + raise KeyError(42) + pass + """) + result = testdir.runpytest(p, "-s") + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "*E*application-level*KeyError*42*", + ]) + def app_test_raises(): info = raises(TypeError, id) assert info.type is TypeError From fijal at codespeak.net Sun Jun 6 17:34:23 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 17:34:23 +0200 (CEST) Subject: [pypy-svn] r75146 - in pypy/trunk: . pypy/annotation pypy/annotation/test pypy/module/_codecs pypy/module/sys pypy/objspace/std pypy/rpython pypy/rpython/lltypesystem pypy/rpython/test Message-ID: <20100606153423.2E211282BF6@codespeak.net> Author: fijal Date: Sun Jun 6 17:34:21 2010 New Revision: 75146 Modified: pypy/trunk/ (props changed) pypy/trunk/pypy/annotation/binaryop.py pypy/trunk/pypy/annotation/builtin.py pypy/trunk/pypy/annotation/classdef.py pypy/trunk/pypy/annotation/test/test_annrpython.py pypy/trunk/pypy/module/_codecs/interp_codecs.py pypy/trunk/pypy/module/sys/__init__.py pypy/trunk/pypy/module/sys/interp_encoding.py pypy/trunk/pypy/objspace/std/unicodetype.py pypy/trunk/pypy/rpython/lltypesystem/rstr.py pypy/trunk/pypy/rpython/rbuiltin.py pypy/trunk/pypy/rpython/test/test_rbuiltin.py Log: Merge encodings-unfreeze branch. This should kill freezing of encodings module from lib-python. Modified: pypy/trunk/pypy/annotation/binaryop.py ============================================================================== --- pypy/trunk/pypy/annotation/binaryop.py (original) +++ pypy/trunk/pypy/annotation/binaryop.py Sun Jun 6 17:34:21 2010 @@ -442,7 +442,7 @@ return SomeUnicodeString() class __extend__(pairtype(SomeString, SomeUnicodeString), - pairtype(SomeString, SomeUnicodeString)): + pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") Modified: pypy/trunk/pypy/annotation/builtin.py ============================================================================== --- pypy/trunk/pypy/annotation/builtin.py (original) +++ pypy/trunk/pypy/annotation/builtin.py Sun Jun 6 17:34:21 2010 @@ -272,6 +272,12 @@ def OSError_init(s_self, *args): pass +def UnicodeDecodeError_init(s_self, *args): + pass + +def UnicodeEncodeError_init(s_self, *args): + pass + def WindowsError_init(s_self, *args): pass @@ -390,6 +396,8 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) +BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init +BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError Modified: pypy/trunk/pypy/annotation/classdef.py ============================================================================== --- pypy/trunk/pypy/annotation/classdef.py (original) +++ pypy/trunk/pypy/annotation/classdef.py Sun Jun 6 17:34:21 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString + SomeString, SomeUnicodeString from pypy.annotation import description @@ -439,6 +439,16 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, + UnicodeDecodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeString(), + 'encoding': SomeString(), + 'reason': SomeString()}, + UnicodeEncodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeUnicodeString(), + 'encoding': SomeString(), + 'reason': SomeString()} } try: Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Sun Jun 6 17:34:21 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_unicode_decode_error(self): + def f(): + try: + raise UnicodeDecodeError("x", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + return ude.end + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInteger) + def g(n): return [0,1,2,n] Modified: pypy/trunk/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/interp_codecs.py Sun Jun 6 17:34:21 2010 @@ -2,6 +2,7 @@ from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder +from pypy.rlib.objectmodel import we_are_translated class CodecState(object): def __init__(self, space): @@ -52,6 +53,9 @@ return replace, newpos return unicode_call_errorhandler + def _freeze_(self): + assert not self.codec_search_path + return False def register_codec(space, w_search_function): """register(search_function) @@ -75,6 +79,8 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ + assert not (space.config.translating and not we_are_translated()), \ + "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() w_result = state.codec_search_cache.get(normalized_encoding, None) @@ -215,11 +221,8 @@ else: encoding = space.str_w(w_encoding) w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) - if space.is_true(w_encoder): - w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) - return space.getitem(w_res, space.wrap(0)) - else: - assert 0, "XXX, what to do here?" + w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) + return space.getitem(w_res, space.wrap(0)) encode.unwrap_spec = [ObjSpace, W_Root, W_Root, str] def buffer_encode(space, s, errors='strict'): Modified: pypy/trunk/pypy/module/sys/__init__.py ============================================================================== --- pypy/trunk/pypy/module/sys/__init__.py (original) +++ pypy/trunk/pypy/module/sys/__init__.py Sun Jun 6 17:34:21 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.interpreter.error import OperationError +from pypy.rlib.objectmodel import we_are_translated import sys class Module(MixedModule): @@ -92,8 +93,12 @@ self.space.setitem(w_modules, w_name, w_module) def startup(self, space): - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) + if space.config.translating and not we_are_translated(): + # don't get the filesystemencoding at translation time + assert self.filesystemencoding is None + else: + from pypy.module.sys.interp_encoding import _getfilesystemencoding + self.filesystemencoding = _getfilesystemencoding(space) def getmodule(self, name): space = self.space Modified: pypy/trunk/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/trunk/pypy/module/sys/interp_encoding.py (original) +++ pypy/trunk/pypy/module/sys/interp_encoding.py Sun Jun 6 17:34:21 2010 @@ -1,5 +1,6 @@ import sys from pypy.rlib import rlocale +from pypy.rlib.objectmodel import we_are_translated def getdefaultencoding(space): """Return the current default string encoding used by the Unicode @@ -18,6 +19,8 @@ space.sys.defaultencoding = encoding def get_w_default_encoder(space): + assert not (space.config.translating and not we_are_translated()), \ + "get_w_default_encoder() should not be called during translation" w_encoding = space.wrap(space.sys.defaultencoding) mod = space.getbuiltinmodule("_codecs") w_lookup = space.getattr(mod, space.wrap("lookup")) @@ -40,6 +43,8 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: + if loc_codeset == 'ANSI_X3.4-1968': + loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), Modified: pypy/trunk/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/trunk/pypy/objspace/std/unicodetype.py (original) +++ pypy/trunk/pypy/objspace/std/unicodetype.py Sun Jun 6 17:34:21 2010 @@ -3,6 +3,8 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii,\ + unicode_encode_utf_8, unicode_encode_ascii from sys import maxint @@ -183,13 +185,27 @@ return encoding, errors def encode_object(space, w_object, encoding, errors): - # XXX write down shortcuts for performance for common encodings, - # just like CPython if encoding is None: # Get the encoder functions as a wrapped object. # This lookup is cached. w_encoder = space.sys.get_w_default_encoder() else: + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_ascii(u, len(u), None)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_utf_8(u, len(u), None)) + except UnicodeEncodeError, uee: + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([ + space.wrap(uee.encoding), + space.wrap(uee.object), + space.wrap(uee.start), + space.wrap(uee.end), + space.wrap(uee.reason)])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -205,9 +221,23 @@ return w_retval def decode_object(space, w_obj, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") if encoding is None: encoding = getdefaultencoding(space) + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_ascii(s, len(s), None)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_utf_8(s, len(s), None)[0]) + except UnicodeDecodeError, ude: + raise OperationError(space.w_UnicodeDecodeError, space.newtuple( + [space.wrap(ude.encoding), space.wrap(ude.object), + space.wrap(ude.start), space.wrap(ude.end), + space.wrap(ude.reason)])) + w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: w_retval = space.call_function(w_decode, w_obj, space.wrap(encoding)) Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rstr.py Sun Jun 6 17:34:21 2010 @@ -18,6 +18,7 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -296,7 +297,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError + raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' Modified: pypy/trunk/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/rbuiltin.py Sun Jun 6 17:34:21 2010 @@ -270,6 +270,37 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) +def rtype_UnicodeDecodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeDecodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + TPS = [hop.args_r[0], r_str, r_str, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + +def rtype_UnicodeEncodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeEncodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + r_unicode = hop.rtyper.type_system.rstr.unicode_repr + TPS = [hop.args_r[0], r_str, r_unicode, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + def rtype_WindowsError__init__(hop): if hop.nb_args == 2: raise TyperError("WindowsError() should not be called with " @@ -329,6 +360,8 @@ BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( rtype_OSError__init__) +BUILTIN_TYPER[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = rtype_UnicodeDecodeError_init +BUILTIN_TYPER[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = rtype_UnicodeEncodeError_init try: WindowsError Modified: pypy/trunk/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/test/test_rbuiltin.py Sun Jun 6 17:34:21 2010 @@ -496,6 +496,35 @@ res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy()) assert res == 123 + def test_unicode_errors(self): + def f(): + try: + raise UnicodeDecodeError("xx", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == "x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + + def f(): + try: + raise UnicodeEncodeError("xx", u"x", 0, 1, "reason") + except UnicodeEncodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == u"x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): From fijal at codespeak.net Sun Jun 6 17:34:43 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 17:34:43 +0200 (CEST) Subject: [pypy-svn] r75147 - pypy/branch/unfreeze-encodings Message-ID: <20100606153443.D4FD3282BF6@codespeak.net> Author: fijal Date: Sun Jun 6 17:34:42 2010 New Revision: 75147 Removed: pypy/branch/unfreeze-encodings/ Log: Remove merged branch From fijal at codespeak.net Sun Jun 6 17:35:30 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 17:35:30 +0200 (CEST) Subject: [pypy-svn] r75148 - pypy/branch/os-read-speedup Message-ID: <20100606153530.E38D1282BF6@codespeak.net> Author: fijal Date: Sun Jun 6 17:35:29 2010 New Revision: 75148 Added: pypy/branch/os-read-speedup/ (props changed) - copied from r75147, pypy/trunk/ Log: Experiment a bit with speeding os.read From fijal at codespeak.net Sun Jun 6 17:46:40 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 17:46:40 +0200 (CEST) Subject: [pypy-svn] r75149 - pypy/branch/os-read-speedup/pypy/rpython/lltypesystem Message-ID: <20100606154640.5F68D282BF6@codespeak.net> Author: fijal Date: Sun Jun 6 17:46:38 2010 New Revision: 75149 Modified: pypy/branch/os-read-speedup/pypy/rpython/lltypesystem/rffi.py Log: Reintroduce not using malloc_nonmovable Modified: pypy/branch/os-read-speedup/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/os-read-speedup/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/os-read-speedup/pypy/rpython/lltypesystem/rffi.py Sun Jun 6 17:46:38 2010 @@ -645,7 +645,7 @@ """ str_chars_offset = (offsetof(STRTYPE, 'chars') + \ itemoffsetof(STRTYPE.chars, 0)) - gc_buf = rgc.malloc_nonmovable(STRTYPE, count) + gc_buf = lltype.nullptr(STRTYPE) # rgc.malloc_nonmovable(STRTYPE, count) if gc_buf: realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset raw_buf = cast(TYPEP, realbuf) From benjamin at codespeak.net Sun Jun 6 18:17:27 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 6 Jun 2010 18:17:27 +0200 (CEST) Subject: [pypy-svn] r75150 - in pypy/branch/fast-forward/pypy/module/sys: . test Message-ID: <20100606161727.E8291282BF6@codespeak.net> Author: benjamin Date: Sun Jun 6 18:17:26 2010 New Revision: 75150 Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Log: alias maxsize to maxint Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Sun Jun 6 18:17:26 2010 @@ -18,7 +18,8 @@ '__doc__' : '(space.wrap("PyPy sys module"))', 'platform' : 'space.wrap(sys.platform)', - 'maxint' : 'space.wrap(sys.maxint)', + 'maxint' : 'space.wrap(sys.maxint)', + 'maxsize' : 'space.wrap(sys.maxsize)', 'byteorder' : 'space.wrap(sys.byteorder)', 'maxunicode' : 'space.wrap(vm.MAXUNICODE)', 'maxint' : 'space.wrap(sys.maxint)', Modified: pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Sun Jun 6 18:17:26 2010 @@ -390,6 +390,7 @@ assert isinstance(sys.executable, basestring) assert isinstance(sys.hexversion, int) assert isinstance(sys.maxint, int) + assert isinstance(sys.maxsize, int) assert isinstance(sys.maxunicode, int) assert isinstance(sys.platform, basestring) #assert isinstance(sys.prefix, basestring) -- not present! From benjamin at codespeak.net Sun Jun 6 18:24:44 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 6 Jun 2010 18:24:44 +0200 (CEST) Subject: [pypy-svn] r75151 - pypy/branch/fast-forward/pypy/tool/pytest/run-script Message-ID: <20100606162444.EB029282BF6@codespeak.net> Author: benjamin Date: Sun Jun 6 18:24:43 2010 New Revision: 75151 Modified: pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Log: test_support.TestSkipped is now unittest.SkipTest Modified: pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/run-script/regrverbose.py Sun Jun 6 18:24:43 2010 @@ -1,17 +1,18 @@ # refer to 2.4.1/test/regrtest.py's runtest() for comparison import sys +import unittest from test import test_support test_support.verbose = int(sys.argv[1]) sys.argv[:] = sys.argv[2:] -modname = sys.argv[0] +modname = sys.argv[0] impname = 'test.' + modname try: mod = __import__(impname, globals(), locals(), [modname]) indirect_test = getattr(mod, 'test_main', None) if indirect_test is not None: indirect_test() -except test_support.TestSkipped: +except unittest.SkipTest: sys.stderr.write("="*26 + "skipped" + "="*26 + "\n") raise -# else the test already ran during import +# else the test already ran during import From hpk at codespeak.net Sun Jun 6 19:04:42 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 6 Jun 2010 19:04:42 +0200 (CEST) Subject: [pypy-svn] r75152 - pypy/branch/fast-forward/py/_code Message-ID: <20100606170442.CAF9C282BF6@codespeak.net> Author: hpk Date: Sun Jun 6 19:04:41 2010 New Revision: 75152 Modified: pypy/branch/fast-forward/py/_code/source.py Log: copy py-trunk fix wrt to py.code.compile Modified: pypy/branch/fast-forward/py/_code/source.py ============================================================================== --- pypy/branch/fast-forward/py/_code/source.py (original) +++ pypy/branch/fast-forward/py/_code/source.py Sun Jun 6 19:04:41 2010 @@ -17,6 +17,8 @@ """ a immutable object holding a source code fragment, possibly deindenting it. """ + _counter = 0 + def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -196,9 +198,11 @@ _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno if not filename: - filename = '' % (fn, lineno) + filename = '<%d-codegen %s:%d>' % (self._counter, fn, lineno) else: - filename = '' % (filename, fn, lineno) + filename = '<%d-codegen %r %s:%d>' % (self._counter, filename, fn, lineno) + self.__class__._counter += 1 + source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) @@ -226,6 +230,7 @@ py.std.inspect.modulesbyfile[filename] = None py.std.sys.modules[None] = m m.__loader__ = 1 + assert filename not in py.std.linecache.cache, filename py.std.linecache.cache[filename] = (1, None, lines, filename) return co From hpk at codespeak.net Sun Jun 6 19:07:04 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 6 Jun 2010 19:07:04 +0200 (CEST) Subject: [pypy-svn] r75153 - pypy/trunk/py/_code Message-ID: <20100606170704.6412B282BF6@codespeak.net> Author: hpk Date: Sun Jun 6 19:07:03 2010 New Revision: 75153 Modified: pypy/trunk/py/_code/source.py Log: also copy the py.code.compile fix to trunk (it can obscure/fail on traceback-printing, especially with generated code entries being in the traceback) Modified: pypy/trunk/py/_code/source.py ============================================================================== --- pypy/trunk/py/_code/source.py (original) +++ pypy/trunk/py/_code/source.py Sun Jun 6 19:07:03 2010 @@ -17,6 +17,7 @@ """ a immutable object holding a source code fragment, possibly deindenting it. """ + _compilecounter = 0 def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -195,10 +196,12 @@ if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno + base = "<%d-codegen " % self._compilecounter + self.__class__._compilecounter += 1 if not filename: - filename = '' % (fn, lineno) + filename = base + '%s:%d>' % (fn, lineno) else: - filename = '' % (filename, fn, lineno) + filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) From fijal at codespeak.net Sun Jun 6 23:12:52 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jun 2010 23:12:52 +0200 (CEST) Subject: [pypy-svn] r75158 - in pypy/trunk/pypy/jit/metainterp: . test Message-ID: <20100606211252.D986F282BF6@codespeak.net> Author: fijal Date: Sun Jun 6 23:12:51 2010 New Revision: 75158 Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Log: Issue545 testing CALL_PURE should force caches in case it's not completely avoided Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py Sun Jun 6 23:12:51 2010 @@ -1066,7 +1066,7 @@ return None def emitting_operation(self, op): - if op.has_no_side_effect(): + if op.opnum != rop.CALL_PURE and op.has_no_side_effect(): return if op.is_ovf(): return @@ -1079,6 +1079,7 @@ return if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or + opnum == rop.CALL_PURE or opnum == rop.CALL_ASSEMBLER): if opnum == rop.CALL_ASSEMBLER: effectinfo = None Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Sun Jun 6 23:12:51 2010 @@ -2586,6 +2586,16 @@ ''' self.optimize_loop(ops, 'Not, Not', ops) + def test_call_pure_invalidates_caches(self): + ops = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call_pure(p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + self.optimize_loop(ops, 'Not, Not', ops) + def test_vref_nonvirtual_nonescape(self): ops = """ [p1] From getxsick at codespeak.net Mon Jun 7 01:36:10 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 7 Jun 2010 01:36:10 +0200 (CEST) Subject: [pypy-svn] r75159 - pypy/trunk/pypy/doc Message-ID: <20100606233610.3E762282BF6@codespeak.net> Author: getxsick Date: Mon Jun 7 01:36:08 2010 New Revision: 75159 Modified: pypy/trunk/pypy/doc/objspace.txt Log: update the URL Modified: pypy/trunk/pypy/doc/objspace.txt ============================================================================== --- pypy/trunk/pypy/doc/objspace.txt (original) +++ pypy/trunk/pypy/doc/objspace.txt Mon Jun 7 01:36:08 2010 @@ -552,7 +552,7 @@ A number of options for configuration is here in `traceconfig.py`_. -.. _`found here` : getting-started.html#tracing-bytecode-and-operations-on-objects +.. _`found here` : getting-started-dev.html#tracing-bytecode-and-operations-on-objects .. _`Abstract Interpretation`: theory.html#abstract-interpretation .. _`traceconfig.py`: ../tool/traceconfig.py From dan at codespeak.net Mon Jun 7 02:59:44 2010 From: dan at codespeak.net (dan at codespeak.net) Date: Mon, 7 Jun 2010 02:59:44 +0200 (CEST) Subject: [pypy-svn] r75160 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100607005944.D6A8E282BF6@codespeak.net> Author: dan Date: Mon Jun 7 02:59:43 2010 New Revision: 75160 Modified: pypy/trunk/pypy/module/cpyext/datetime.py pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Added PyDelta_Check() and test. Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Mon Jun 7 02:59:43 2010 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pyobject import PyObject -from pypy.module.cpyext.api import cpython_api +from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL from pypy.module.cpyext.import_ import PyImport_Import @cpython_api([], lltype.Void) @@ -14,3 +14,14 @@ w_datetime, "time", space.wrap(hour), space.wrap(minute), space.wrap(second), space.wrap(usecond)) + + at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) +def PyDelta_Check(space, w_obj): + """Return true if ob is of type PyDateTime_DeltaType or a subtype of + PyDateTime_DeltaType. ob must not be NULL. + """ + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import timedelta + return isinstance(obj, timedelta) + """)) Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Mon Jun 7 02:59:43 2010 @@ -23,7 +23,7 @@ _inittab = lltype.Void PyThreadState = lltype.Void PyInterpreterState = lltype.Void -PyOS_sighandler_t = lltype.Void +#PyOS_sighandler_t = lltype.Void Py_UNICODE = lltype.Void PyCompilerFlags = lltype.Void _node = lltype.Void @@ -616,13 +616,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_Check(space, ob): - """Return true if ob is of type PyDateTime_DeltaType or a subtype of - PyDateTime_DeltaType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyDelta_CheckExact(space, ob): """Return true if ob is of type PyDateTime_DeltaType. ob must not be NULL. Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 02:59:43 2010 @@ -5,3 +5,15 @@ def test_time(self, space, api): w_time = api.PyTime_FromTime(23, 15, 40, 123456) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' + def test_deltacheck(self, space, api): + w_delta = space.appexec([space.wrap(3), space.wrap(15)], """(days, seconds): + from datetime import timedelta + return timedelta(days, seconds) + """) + assert api.PyDelta_Check(w_delta) + + w_delta = space.appexec([space.wrap(1), space.wrap(1), space.wrap(1999)], """(day, month, year): + from datetime import datetime + return datetime.now() - datetime(year, month, day) + """) + assert api.PyDelta_Check(w_delta) From afa at codespeak.net Mon Jun 7 09:26:52 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 09:26:52 +0200 (CEST) Subject: [pypy-svn] r75161 - pypy/trunk/pypy/module/cpyext Message-ID: <20100607072652.C3909282BF6@codespeak.net> Author: afa Date: Mon Jun 7 09:26:51 2010 New Revision: 75161 Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py Log: Always raise an exception when res==-1 Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/slotdefs.py (original) +++ pypy/trunk/pypy/module/cpyext/slotdefs.py Mon Jun 7 09:26:51 2010 @@ -41,7 +41,7 @@ func_init = rffi.cast(initproc, func) res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) if rffi.cast(lltype.Signed, res) == -1: - space.fromcache(State).check_and_raise_exception() + space.fromcache(State).check_and_raise_exception(always=True) return None def wrap_unaryfunc(space, w_self, w_args, func): @@ -216,7 +216,7 @@ @cpython_api([PyObject], PyObject, external=False) def slot_tp_str(space, w_self): return space.str(w_self) - + @cpython_api([PyObject], PyObject, external=False) def slot_nb_int(space, w_self): return space.int(w_self) From arigo at codespeak.net Mon Jun 7 10:28:12 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 10:28:12 +0200 (CEST) Subject: [pypy-svn] r75162 - pypy/trunk/pypy/module/imp Message-ID: <20100607082812.5361E282BD8@codespeak.net> Author: arigo Date: Mon Jun 7 10:28:10 2010 New Revision: 75162 Modified: pypy/trunk/pypy/module/imp/importing.py Log: No-op changes: uses "< 0" instead of "== -1", which allows the annotation-time asserts to be removed. Modified: pypy/trunk/pypy/module/imp/importing.py ============================================================================== --- pypy/trunk/pypy/module/imp/importing.py (original) +++ pypy/trunk/pypy/module/imp/importing.py Mon Jun 7 10:28:10 2010 @@ -178,13 +178,11 @@ else: level = 0 first = None - while last_dot != -1: - assert last_dot >= 0 # bah + while last_dot >= 0: last_dot = modulename.find('.', last_dot + 1) - if last_dot == -1: + if last_dot < 0: w_mod = check_sys_modules_w(space, modulename) else: - assert last_dot >= 0 w_mod = check_sys_modules_w(space, modulename[:last_dot]) if w_mod is None or space.is_w(w_mod, space.w_None): return None From arigo at codespeak.net Mon Jun 7 11:13:27 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 11:13:27 +0200 (CEST) Subject: [pypy-svn] r75163 - in pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem: . test Message-ID: <20100607091327.E7AB4282B9C@codespeak.net> Author: arigo Date: Mon Jun 7 11:13:26 2010 New Revision: 75163 Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py Log: Revert r74920: it's wrong, two GcStructs with the same name and the same fields are equal even if their RuntimeTypeInfo is different. Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py Mon Jun 7 11:13:26 2010 @@ -64,30 +64,17 @@ class LowLevelType(object): + # the following line prevents '__cached_hash' to be in the __dict__ of + # the instance, which is needed for __eq__() and __hash__() to work. + __slots__ = ['__dict__', '__cached_hash'] def __eq__(self, other): - if self.__class__ is not other.__class__: - return False - if self is other: - return True - items1 = self._get_dict_as_list() - items2 = other._get_dict_as_list() - if len(items1) != len(items2): - return False - for (k1, v1), (k2, v2) in zip(items1, items2): - if k1 != k2 or not safe_equal(v1, v2): - return False - return True + return self.__class__ is other.__class__ and ( + self is other or safe_equal(self.__dict__, other.__dict__)) def __ne__(self, other): return not (self == other) - def _get_dict_as_list(self): - result = [(key, value) for (key, value) in self.__dict__.items() - if not key.startswith('_HIDDEN_')] - result.sort() - return result - _is_compatible = __eq__ def _enforce(self, value): @@ -97,26 +84,27 @@ def __hash__(self): # cannot use saferecursive() -- see test_lltype.test_hash(). - # NB. the _cached_hash should neither be used nor updated + # NB. the __cached_hash should neither be used nor updated # if we enter with hash_level > 0, because the computed # __hash__ can be different in this situation. hash_level = 0 try: hash_level = TLS.nested_hash_level if hash_level == 0: - return self._HIDDEN_cached_hash + return self.__cached_hash except AttributeError: pass if hash_level >= 3: return 0 - items = self._get_dict_as_list() + items = self.__dict__.items() + items.sort() TLS.nested_hash_level = hash_level + 1 try: result = hash((self.__class__,) + tuple(items)) finally: TLS.nested_hash_level = hash_level if hash_level == 0: - self._HIDDEN_cached_hash = result + self.__cached_hash = result return result # due to this dynamic hash value, we should forbid @@ -295,13 +283,11 @@ return _struct(self, n, initialization='example') class RttiStruct(Struct): - _HIDDEN_runtime_type_info = None + _runtime_type_info = None def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): - if self._HIDDEN_runtime_type_info is None: - self._HIDDEN_runtime_type_info = opaqueptr(RuntimeTypeInfo, - name=self._name, - about=self)._obj + if self._runtime_type_info is None: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -311,7 +297,7 @@ castable(T.TO.ARGS[0], Ptr(self)) < 0): raise TypeError("expected a runtime type info function " "implementation, got: %s" % funcptr) - self._HIDDEN_runtime_type_info.query_funcptr = funcptr + self._runtime_type_info.query_funcptr = funcptr if destrptr is not None : T = typeOf(destrptr) if (not isinstance(T, Ptr) or @@ -321,7 +307,7 @@ castable(T.TO.ARGS[0], Ptr(self)) < 0): raise TypeError("expected a destructor function " "implementation, got: %s" % destrptr) - self._HIDDEN_runtime_type_info.destructor_funcptr = destrptr + self._runtime_type_info.destructor_funcptr = destrptr class GcStruct(RttiStruct): _gckind = 'gc' @@ -1862,15 +1848,15 @@ if not isinstance(GCSTRUCT, RttiStruct): raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT GCSTRUCT._attach_runtime_type_info_funcptr(funcptr, destrptr) - return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._HIDDEN_runtime_type_info) + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) def getRuntimeTypeInfo(GCSTRUCT): if not isinstance(GCSTRUCT, RttiStruct): raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT - if GCSTRUCT._HIDDEN_runtime_type_info is None: + if GCSTRUCT._runtime_type_info is None: raise ValueError, ("no attached runtime type info for GcStruct %s" % GCSTRUCT._name) - return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._HIDDEN_runtime_type_info) + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) def runtime_type_info(p): T = typeOf(p) Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py Mon Jun 7 11:13:26 2010 @@ -373,13 +373,7 @@ Sbis = GcStruct('s', ('x', Signed)) attachRuntimeTypeInfo(Sbis) assert getRuntimeTypeInfo(Sbis) != pinf0 - #assert Sbis != S # the attached runtime type info distinguishes them - # --- disabled for now, not really useful. Instead we have the more - # important property: - Ster = GcStruct('s', ('x', Signed)) - h = hash(Ptr(Ster)) - attachRuntimeTypeInfo(Ster) - assert h == hash(Ptr(Ster)) + assert Sbis != S # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): S = GcStruct('s', ('x', Signed)) From afa at codespeak.net Mon Jun 7 11:35:13 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 11:35:13 +0200 (CEST) Subject: [pypy-svn] r75164 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100607093513.B3C49282B9C@codespeak.net> Author: afa Date: Mon Jun 7 11:35:11 2010 New Revision: 75164 Modified: pypy/trunk/pypy/module/cpyext/datetime.py pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Implement PyDate, PyTime, PyDateTime: constructors, check functions, and member access. Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Mon Jun 7 11:35:11 2010 @@ -2,26 +2,159 @@ from pypy.module.cpyext.pyobject import PyObject from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL from pypy.module.cpyext.import_ import PyImport_Import +from pypy.interpreter.error import OperationError +from pypy.tool.sourcetools import func_renamer @cpython_api([], lltype.Void) def PyDateTime_IMPORT(space): return - at cpython_api([rffi.INT, rffi.INT, rffi.INT, rffi.INT], PyObject) +PyDateTime_Date = PyObject +PyDateTime_Time = PyObject +PyDateTime_DateTime = PyObject + +# Check functions + +def make_check_function(func_name, type_name): + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name) + def check(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return isinstance(obj, datatype) + """ % (type_name,))) + except OperationError: + return 0 + + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name + "Exact") + def check_exact(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return type(obj) is datatype + """ % (type_name,))) + except OperationError: + return 0 + +make_check_function("PyDateTime_Check", "datetime") +make_check_function("PyDate_Check", "date") +make_check_function("PyTime_Check", "time") +make_check_function("PyDelta_Check", "timedelta") + +# Constructors + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDate_FromDate(space, year, month, day): + """Return a datetime.date object with the specified year, month and day. + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "date", + space.wrap(year), space.wrap(month), space.wrap(day)) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) def PyTime_FromTime(space, hour, minute, second, usecond): + """Return a ``datetime.time`` object with the specified hour, minute, second and + microsecond.""" w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "time", space.wrap(hour), space.wrap(minute), space.wrap(second), space.wrap(usecond)) - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_Check(space, w_obj): - """Return true if ob is of type PyDateTime_DeltaType or a subtype of - PyDateTime_DeltaType. ob must not be NULL. - """ - return space.is_true( - space.appexec([w_obj], """(obj): - from datetime import timedelta - return isinstance(obj, timedelta) - """)) + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): + """Return a datetime.datetime object with the specified year, month, day, hour, + minute, second and microsecond. + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "datetime", + space.wrap(year), space.wrap(month), space.wrap(day), + space.wrap(hour), space.wrap(minute), space.wrap(second), + space.wrap(usecond)) + raise NotImplementedError + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDelta_FromDSU(space, days, seconds, useconds): + """Return a datetime.timedelta object representing the given number of days, + seconds and microseconds. Normalization is performed so that the resulting + number of microseconds and seconds lie in the ranges documented for + datetime.timedelta objects. + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "timedelta", + space.wrap(days), space.wrap(seconds), space.wrap(useconds)) + +# Accessors + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_YEAR(space, w_obj): + """Return the year, as a positive int. + """ + return space.getattr(w_obj, space.wrap("year")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_MONTH(space, w_obj): + """Return the month, as an int from 1 through 12. + """ + return space.getattr(w_obj, space.wrap("month")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_DAY(space, w_obj): + """Return the day, as an int from 1 through 31. + """ + return space.getattr(w_obj, space.wrap("day")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Mon Jun 7 11:35:11 2010 @@ -574,55 +574,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_Check(space, ob): - """Return true if ob is of type PyDateTime_DateType or a subtype of - PyDateTime_DateType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_Check(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType or a subtype of - PyDateTime_DateTimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType. ob must not - be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_Check(space, ob): - """Return true if ob is of type PyDateTime_TimeType or a subtype of - PyDateTime_TimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_TimeType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DeltaType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyTZInfo_Check(space, ob): """Return true if ob is of type PyDateTime_TZInfoType or a subtype of PyDateTime_TZInfoType. ob must not be NULL. @@ -636,94 +587,6 @@ """ raise NotImplementedError - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): - """Return a datetime.date object with the specified year, month and day. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): - """Return a datetime.datetime object with the specified year, month, day, hour, - minute, second and microsecond. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): - """Return a datetime.timedelta object representing the given number of days, - seconds and microseconds. Normalization is performed so that the resulting - number of microseconds and seconds lie in the ranges documented for - datetime.timedelta objects. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_YEAR(space, o): - """Return the year, as a positive int. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_MONTH(space, o): - """Return the month, as an int from 1 through 12. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_DAY(space, o): - """Return the day, as an int from 1 through 31. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - @cpython_api([PyObject], PyObject) def PyDateTime_FromTimestamp(space, args): """Create and return a new datetime.datetime object given an argument tuple Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 11:35:11 2010 @@ -2,18 +2,62 @@ from pypy.module.cpyext.test.test_api import BaseApiTest class TestDatetime(BaseApiTest): + def test_date(self, space, api): + w_date = api.PyDate_FromDate(2010, 06, 03) + assert space.unwrap(space.str(w_date)) == '2010-06-03' + + assert api.PyDate_Check(w_date) + assert api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date)])) == ( + 2010, 06, 03) + def test_time(self, space, api): w_time = api.PyTime_FromTime(23, 15, 40, 123456) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' - def test_deltacheck(self, space, api): - w_delta = space.appexec([space.wrap(3), space.wrap(15)], """(days, seconds): + + assert api.PyTime_Check(w_time) + assert api.PyTime_CheckExact(w_time) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_TIME_GET_HOUR(w_time), + api.PyDateTime_TIME_GET_MINUTE(w_time), + api.PyDateTime_TIME_GET_SECOND(w_time), + api.PyDateTime_TIME_GET_MICROSECOND(w_time)])) == ( + 23, 15, 40, 123456) + + def test_datetime(self, space, api): + w_date = api.PyDateTime_FromDateAndTime( + 2010, 06, 03, 23, 15, 40, 123456) + assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456' + + assert api.PyDateTime_Check(w_date) + assert api.PyDateTime_CheckExact(w_date) + assert api.PyDate_Check(w_date) + assert not api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date), + api.PyDateTime_DATE_GET_HOUR(w_date), + api.PyDateTime_DATE_GET_MINUTE(w_date), + api.PyDateTime_DATE_GET_SECOND(w_date), + api.PyDateTime_DATE_GET_MICROSECOND(w_date)])) == ( + 2010, 06, 03, 23, 15, 40, 123456) + + def test_delta(self, space, api): + w_delta = space.appexec( + [space.wrap(3), space.wrap(15)], """(days, seconds): from datetime import timedelta return timedelta(days, seconds) """) assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) - w_delta = space.appexec([space.wrap(1), space.wrap(1), space.wrap(1999)], """(day, month, year): - from datetime import datetime - return datetime.now() - datetime(year, month, day) - """) + w_delta = api.PyDelta_FromDSU(10, 20, 30) assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) From arigo at codespeak.net Mon Jun 7 11:35:21 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 11:35:21 +0200 (CEST) Subject: [pypy-svn] r75165 - in pypy/branch/blackhole-improvement/pypy: jit/codewriter/test rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gctransform/test rpython/test translator/c/test Message-ID: <20100607093521.B5E16282BD8@codespeak.net> Author: arigo Date: Mon Jun 7 11:35:19 2010 New Revision: 75165 Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rclass.py pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/branch/blackhole-improvement/pypy/rpython/test/test_llann.py pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py pypy/branch/blackhole-improvement/pypy/translator/c/test/test_genc.py pypy/branch/blackhole-improvement/pypy/translator/c/test/test_refcount.py Log: Re-fix for r74920: make sure that the hash of a GcStruct doesn't change when we call attachRuntimeTypeInfo() on it the first time. The fix is that we have to build the GcStruct with the new rtti=True argument; then it gets attached a runtime type info at construction-time. It's not possible any more to add a runtime type info to a GcStruct built without the rtti argument. Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py Mon Jun 7 11:35:19 2010 @@ -429,7 +429,7 @@ def test_malloc_new_with_destructor(): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - S = lltype.GcStruct('S', ('parent', rclass.OBJECT)) + S = lltype.GcStruct('S', ('parent', rclass.OBJECT), rtti=True) DESTRUCTOR = lltype.FuncType([lltype.Ptr(S)], lltype.Void) destructor = lltype.functionptr(DESTRUCTOR, 'destructor') lltype.attachRuntimeTypeInfo(S, destrptr=destructor) Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/lltype.py Mon Jun 7 11:35:19 2010 @@ -285,9 +285,17 @@ class RttiStruct(Struct): _runtime_type_info = None + def _install_extras(self, rtti=False, **kwds): + if rtti: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, + name=self._name, + about=self)._obj + Struct._install_extras(self, **kwds) + def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + raise TypeError("attachRuntimeTypeInfo: %r must have been built " + "with the rtti=True argument" % (self,)) if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/rclass.py Mon Jun 7 11:35:19 2010 @@ -13,7 +13,7 @@ Ptr, Struct, GcStruct, malloc, \ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ - Array, Char, Void, attachRuntimeTypeInfo, \ + Array, Char, Void, \ FuncType, Bool, Signed, functionptr, FuncType, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -60,7 +60,8 @@ CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), hints = {'immutable': True, 'shouldntbenull': True, - 'typeptr': True}) + 'typeptr': True}, + rtti = True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), @@ -348,18 +349,20 @@ if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) + kwds = {} + if self.gcflavor == 'gc': + kwds['rtti'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, - *llfields) + *llfields, + **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields - if self.gcflavor == 'gc': - attachRuntimeTypeInfo(self.object_type) def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_lltype.py Mon Jun 7 11:35:19 2010 @@ -361,22 +361,25 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) py.test.raises(ValueError, "getRuntimeTypeInfo(S)") - pinf0 = attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) + pinfx = getRuntimeTypeInfo(S) + pinf0 = attachRuntimeTypeInfo(S) # no-op, really assert pinf0._obj.about == S + assert pinf0 == pinfx pinf = getRuntimeTypeInfo(S) assert pinf == pinf0 pinf1 = getRuntimeTypeInfo(S) assert pinf == pinf1 - Z = GcStruct('z', ('x', Unsigned)) - attachRuntimeTypeInfo(Z) + Z = GcStruct('z', ('x', Unsigned), rtti=True) assert getRuntimeTypeInfo(Z) != pinf0 - Sbis = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(Sbis) + Sbis = GcStruct('s', ('x', Signed), rtti=True) assert getRuntimeTypeInfo(Sbis) != pinf0 assert Sbis != S # the attached runtime type info distinguishes them + Ster = GcStruct('s', ('x', Signed), rtti=True) + assert Sbis != Ster # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -397,12 +400,12 @@ assert pinf._obj.query_funcptr == qp def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) attachRuntimeTypeInfo(S) s = malloc(S) s.x = 0 assert runtime_type_info(s) == getRuntimeTypeInfo(S) - S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + S1 = GcStruct('s1', ('sub', S), ('x', Signed), rtti=True) attachRuntimeTypeInfo(S1) s1 = malloc(S1) s1.sub.x = 0 Modified: pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_refcounting.py Mon Jun 7 11:35:19 2010 @@ -175,7 +175,7 @@ assert len(ops['gc_free']) == 1 def test_deallocator_with_destructor(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -192,9 +192,9 @@ graph, t = make_deallocator(S) def test_caching_dynamic_deallocator(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) - T = lltype.GcStruct("T", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) + S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) + T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): Modified: pypy/branch/blackhole-improvement/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/test/test_llann.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/test/test_llann.py Mon Jun 7 11:35:19 2010 @@ -342,8 +342,7 @@ assert s.items[1].const == 3 def test_getRuntimeTypeInfo(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(): return getRuntimeTypeInfo(S) s = self.annotate(llf, []) @@ -352,8 +351,7 @@ assert s.const == getRuntimeTypeInfo(S) def test_runtime_type_info(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(p): return runtime_type_info(p) s = self.annotate(llf, [annmodel.SomePtr(Ptr(S))]) Modified: pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/test/test_rptr.py Mon Jun 7 11:35:19 2010 @@ -36,8 +36,7 @@ assert s.ll_ptrtype == PS2 def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def ll_example(p): return (runtime_type_info(p), runtime_type_info(p) == getRuntimeTypeInfo(S)) Modified: pypy/branch/blackhole-improvement/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/translator/c/test/test_genc.py (original) +++ pypy/branch/blackhole-improvement/pypy/translator/c/test/test_genc.py Mon Jun 7 11:35:19 2010 @@ -143,10 +143,8 @@ assert f1() == '\x00' def test_runtime_type_info(): - S = GcStruct('s', ('is_actually_s1', Bool)) - S1 = GcStruct('s1', ('sub', S)) - attachRuntimeTypeInfo(S) - attachRuntimeTypeInfo(S1) + S = GcStruct('s', ('is_actually_s1', Bool), rtti=True) + S1 = GcStruct('s1', ('sub', S), rtti=True) def rtti_S(p): if p.is_actually_s1: return getRuntimeTypeInfo(S1) Modified: pypy/branch/blackhole-improvement/pypy/translator/c/test/test_refcount.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/translator/c/test/test_refcount.py (original) +++ pypy/branch/blackhole-improvement/pypy/translator/c/test/test_refcount.py Mon Jun 7 11:35:19 2010 @@ -130,9 +130,8 @@ def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: - S = lltype.GcStruct('S', ('x', lltype.Signed)) + S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): From arigo at codespeak.net Mon Jun 7 12:06:18 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 12:06:18 +0200 (CEST) Subject: [pypy-svn] r75166 - pypy/branch/blackhole-improvement/pypy/jit/tool/test Message-ID: <20100607100618.E0FF6282B9C@codespeak.net> Author: arigo Date: Mon Jun 7 12:06:17 2010 New Revision: 75166 Modified: pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py Log: Fix test. Modified: pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/branch/blackhole-improvement/pypy/jit/tool/test/test_jitoutput.py Mon Jun 7 12:06:17 2010 @@ -41,8 +41,6 @@ assert info.recorded_ops.calls == 0 assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 - assert info.blackholed_ops.total == 0 - assert info.blackholed_ops.pure_calls == 0 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 0 From arigo at codespeak.net Mon Jun 7 12:08:36 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 12:08:36 +0200 (CEST) Subject: [pypy-svn] r75167 - pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test Message-ID: <20100607100836.C033E282B9C@codespeak.net> Author: arigo Date: Mon Jun 7 12:08:35 2010 New Revision: 75167 Modified: pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_boehm.py Log: Fix test. Modified: pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_boehm.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_boehm.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/memory/gctransform/test/test_boehm.py Mon Jun 7 12:08:35 2010 @@ -40,7 +40,7 @@ assert f is not None def test_boehm_finalizer___del__(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -58,7 +58,8 @@ assert f is not None def test_boehm_finalizer_nomix___del___and_pyobj(): - S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) + S = lltype.GcStruct("S", ('x', lltype.Signed), + ('y', lltype.Ptr(lltype.PyObject)), rtti=True) def f(s): s.x = 1 def type_info_S(p): From arigo at codespeak.net Mon Jun 7 12:11:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 12:11:52 +0200 (CEST) Subject: [pypy-svn] r75168 - pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test Message-ID: <20100607101152.53B09282B9C@codespeak.net> Author: arigo Date: Mon Jun 7 12:11:51 2010 New Revision: 75168 Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_llmemory.py Log: Fix test. Modified: pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/blackhole-improvement/pypy/rpython/lltypesystem/test/test_llmemory.py Mon Jun 7 12:11:51 2010 @@ -629,9 +629,19 @@ A = lltype.Array(Address) ptr = lltype.malloc(A, 10, immortal=True) adr = cast_ptr_to_adr(ptr) - int = cast_adr_to_int(adr) - assert isinstance(int, AddressAsInt) - assert cast_int_to_adr(int) == adr - # - assert cast_adr_to_int(NULL) == 0 + i = cast_adr_to_int(adr, mode="symbolic") + assert isinstance(i, AddressAsInt) + assert cast_int_to_adr(i) == adr + assert cast_adr_to_int(NULL, mode="symbolic") == 0 assert cast_int_to_adr(0) == NULL + # + i = cast_adr_to_int(adr, mode="emulated") + assert type(i) is int + i = cast_adr_to_int(NULL, mode="emulated") + assert type(i) is int and i == 0 + # + i = cast_adr_to_int(adr, mode="forced") + assert type(i) is int + #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details + i = cast_adr_to_int(NULL, mode="forced") + assert type(i) is int and i == 0 From arigo at codespeak.net Mon Jun 7 12:13:38 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 12:13:38 +0200 (CEST) Subject: [pypy-svn] r75169 - pypy/branch/blackhole-improvement/pypy/translator/c/test Message-ID: <20100607101338.E5266282B9C@codespeak.net> Author: arigo Date: Mon Jun 7 12:13:37 2010 New Revision: 75169 Modified: pypy/branch/blackhole-improvement/pypy/translator/c/test/test_lladdresses.py Log: Fix test. Modified: pypy/branch/blackhole-improvement/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/blackhole-improvement/pypy/translator/c/test/test_lladdresses.py Mon Jun 7 12:13:37 2010 @@ -198,7 +198,7 @@ S = lltype.Struct("S", ("x", lltype.Signed)) s = lltype.malloc(S, immortal=True) s.x = 42 - integer = cast_adr_to_int(cast_ptr_to_adr(s)) + integer = cast_adr_to_int(cast_ptr_to_adr(s), mode="symbolic") def f(n): if n > 1: i = integer From afa at codespeak.net Mon Jun 7 13:30:57 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 13:30:57 +0200 (CEST) Subject: [pypy-svn] r75170 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100607113057.09117282B9C@codespeak.net> Author: afa Date: Mon Jun 7 13:30:56 2010 New Revision: 75170 Modified: pypy/trunk/pypy/module/cpyext/datetime.py pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: PyDateTime_FromTimestamp, PyDate_FromTimestamp Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Mon Jun 7 13:30:56 2010 @@ -79,6 +79,26 @@ space.wrap(usecond)) raise NotImplementedError + at cpython_api([PyObject], PyObject) +def PyDateTime_FromTimestamp(space, w_args): + """Create and return a new datetime.datetime object given an argument tuple + suitable for passing to datetime.datetime.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("datetime")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + + at cpython_api([PyObject], PyObject) +def PyDate_FromTimestamp(space, w_args): + """Create and return a new datetime.date object given an argument tuple + suitable for passing to datetime.date.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("date")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) def PyDelta_FromDSU(space, days, seconds, useconds): """Return a datetime.timedelta object representing the given number of days, Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Mon Jun 7 13:30:56 2010 @@ -587,20 +587,6 @@ """ raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyDateTime_FromTimestamp(space, args): - """Create and return a new datetime.datetime object given an argument tuple - suitable for passing to datetime.datetime.fromtimestamp(). - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDate_FromTimestamp(space, args): - """Create and return a new datetime.date object given an argument tuple - suitable for passing to datetime.date.fromtimestamp(). - """ - raise NotImplementedError - @cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject) def PyDescr_NewGetSet(space, type, getset): raise NotImplementedError Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 13:30:56 2010 @@ -1,5 +1,6 @@ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.test.test_api import BaseApiTest +import datetime class TestDatetime(BaseApiTest): def test_date(self, space, api): @@ -61,3 +62,13 @@ w_delta = api.PyDelta_FromDSU(10, 20, 30) assert api.PyDelta_Check(w_delta) assert api.PyDelta_CheckExact(w_delta) + + def test_fromtimestamp(self, space, api): + w_args = space.wrap((0,)) + w_date = api.PyDate_FromTimestamp(w_args) + assert space.unwrap(space.str(w_date)) == '1970-01-01' + + w_args = space.wrap((0,)) + w_date = api.PyDateTime_FromTimestamp(w_args) + date = datetime.datetime.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) From arigo at codespeak.net Mon Jun 7 14:53:17 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jun 2010 14:53:17 +0200 (CEST) Subject: [pypy-svn] r75171 - pypy/trunk/pypy/jit/metainterp Message-ID: <20100607125317.60095282BDB@codespeak.net> Author: arigo Date: Mon Jun 7 14:53:14 2010 New Revision: 75171 Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Replace these bogus asserts with "if I did not manage to compile this exit path, give up". Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Mon Jun 7 14:53:14 2010 @@ -1719,7 +1719,8 @@ self.history.record(rop.JUMP, exits, None) target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1729,7 +1730,8 @@ loop_tokens = sd.loop_tokens_exit_frame_with_exception_ref target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests From afa at codespeak.net Mon Jun 7 16:47:42 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 16:47:42 +0200 (CEST) Subject: [pypy-svn] r75176 - pypy/trunk/pypy/module/cpyext Message-ID: <20100607144742.30320282BDB@codespeak.net> Author: afa Date: Mon Jun 7 16:47:40 2010 New Revision: 75176 Modified: pypy/trunk/pypy/module/cpyext/datetime.py Log: Fix translation Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Mon Jun 7 16:47:40 2010 @@ -51,6 +51,9 @@ def PyDate_FromDate(space, year, month, day): """Return a datetime.date object with the specified year, month and day. """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "date", @@ -60,6 +63,10 @@ def PyTime_FromTime(space, hour, minute, second, usecond): """Return a ``datetime.time`` object with the specified hour, minute, second and microsecond.""" + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "time", @@ -71,6 +78,13 @@ """Return a datetime.datetime object with the specified year, month, day, hour, minute, second and microsecond. """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "datetime", @@ -106,6 +120,9 @@ number of microseconds and seconds lie in the ranges documented for datetime.timedelta objects. """ + days = rffi.cast(lltype.Signed, days) + seconds = rffi.cast(lltype.Signed, seconds) + useconds = rffi.cast(lltype.Signed, useconds) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "timedelta", From afa at codespeak.net Mon Jun 7 17:01:30 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 17:01:30 +0200 (CEST) Subject: [pypy-svn] r75177 - pypy/trunk/pypy/module/cpyext/test Message-ID: <20100607150130.E3235282BDB@codespeak.net> Author: afa Date: Mon Jun 7 17:01:29 2010 New Revision: 75177 Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Fix test to work in western timezones: GMT-x Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 17:01:29 2010 @@ -66,7 +66,8 @@ def test_fromtimestamp(self, space, api): w_args = space.wrap((0,)) w_date = api.PyDate_FromTimestamp(w_args) - assert space.unwrap(space.str(w_date)) == '1970-01-01' + date = datetime.date.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) w_args = space.wrap((0,)) w_date = api.PyDateTime_FromTimestamp(w_args) From afa at codespeak.net Mon Jun 7 18:16:06 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 18:16:06 +0200 (CEST) Subject: [pypy-svn] r75178 - in pypy/trunk/pypy/module/cpyext: . include test Message-ID: <20100607161606.4DE55282BDB@codespeak.net> Author: afa Date: Mon Jun 7 18:16:02 2010 New Revision: 75178 Modified: pypy/trunk/pypy/module/cpyext/datetime.py pypy/trunk/pypy/module/cpyext/include/Python.h pypy/trunk/pypy/module/cpyext/include/datetime.h pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Our implmentation of datetime is written in Python. but it does not seem possible to expose Python types with a customized PyObject structure. Invent "macros" like PyDateTime_DELTA_GET_DAYS to access data members. They could be added to CPython IMO. Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Mon Jun 7 18:16:02 2010 @@ -1,18 +1,25 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pyobject import PyObject -from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import ( + cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_renamer +# API import function + @cpython_api([], lltype.Void) -def PyDateTime_IMPORT(space): +def _PyDateTime_Import(space): return PyDateTime_Date = PyObject PyDateTime_Time = PyObject PyDateTime_DateTime = PyObject +PyDeltaObjectStruct = lltype.ForwardReference() +cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct) +PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct) + # Check functions def make_check_function(func_name, type_name): @@ -195,3 +202,19 @@ """Return the microsecond, as an int from 0 through 999999. """ return space.getattr(w_obj, space.wrap("microsecond")) + +# XXX these functions are not present in the Python API +# But it does not seem possible to expose a different structure +# for types defined in a python module like lib/datetime.py. + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_DAYS(space, w_obj): + return space.getattr(w_obj, space.wrap("days")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_SECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("seconds")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("microseconds")) Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Mon Jun 7 18:16:02 2010 @@ -96,6 +96,7 @@ #include "pycobject.h" #include "bufferobject.h" #include "sliceobject.h" +#include "datetime.h" #include "pystate.h" // XXX This shouldn't be included here Modified: pypy/trunk/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/datetime.h (original) +++ pypy/trunk/pypy/module/cpyext/include/datetime.h Mon Jun 7 18:16:02 2010 @@ -0,0 +1,16 @@ +#ifndef DATETIME_H +#define DATETIME_H +#ifdef __cplusplus +extern "C" { +#endif + +#define PyDateTime_IMPORT _PyDateTime_Import() + +typedef struct { + PyObject_HEAD +} PyDateTime_Delta; + +#ifdef __cplusplus +} +#endif +#endif Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 18:16:02 2010 @@ -63,6 +63,12 @@ assert api.PyDelta_Check(w_delta) assert api.PyDelta_CheckExact(w_delta) + assert space.unwrap(space.newtuple([ + api.PyDateTime_DELTA_GET_DAYS(w_delta), + api.PyDateTime_DELTA_GET_SECONDS(w_delta), + api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta)])) == ( + 10, 20, 30) + def test_fromtimestamp(self, space, api): w_args = space.wrap((0,)) w_date = api.PyDate_FromTimestamp(w_args) From afa at codespeak.net Mon Jun 7 18:18:50 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 7 Jun 2010 18:18:50 +0200 (CEST) Subject: [pypy-svn] r75179 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100607161850.620B7282BDB@codespeak.net> Author: afa Date: Mon Jun 7 18:18:49 2010 New Revision: 75179 Modified: pypy/trunk/pypy/module/cpyext/sequence.py pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_sequence.py Log: PySequence_List Modified: pypy/trunk/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/sequence.py (original) +++ pypy/trunk/pypy/module/cpyext/sequence.py Mon Jun 7 18:18:49 2010 @@ -99,6 +99,12 @@ return space.getitem(w_obj, space.wrap(i)) @cpython_api([PyObject], PyObject) +def PySequence_List(space, w_obj): + """Return a list object with the same contents as the arbitrary sequence o. The + returned list is guaranteed to be new.""" + return space.call_function(space.w_list, w_obj) + + at cpython_api([PyObject], PyObject) def PySequence_Tuple(space, w_obj): """Return a tuple object with the same contents as the arbitrary sequence o or NULL on failure. If o is a tuple, a new reference will be returned, Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Mon Jun 7 18:18:49 2010 @@ -2305,12 +2305,6 @@ in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PySequence_List(space, o): - """Return a list object with the same contents as the arbitrary sequence o. The - returned list is guaranteed to be new.""" - raise NotImplementedError - @cpython_api([PyObject], PyObjectP, error=lltype.nullptr(PyObjectP.TO)) def PySequence_Fast_ITEMS(space, o): """Return the underlying array of PyObject pointers. Assumes that o was returned Modified: pypy/trunk/pypy/module/cpyext/test/test_sequence.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_sequence.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_sequence.py Mon Jun 7 18:18:49 2010 @@ -23,6 +23,10 @@ assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + w_seq = api.PySequence_List(w_set) + assert space.type(w_seq) is space.w_list + assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + def test_repeat(self, space, api): def test(seq, count): w_seq = space.wrap(seq) From benjamin at codespeak.net Mon Jun 7 20:03:58 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 7 Jun 2010 20:03:58 +0200 (CEST) Subject: [pypy-svn] r75180 - in pypy/branch/fast-forward/pypy: interpreter module/__builtin__ module/__builtin__/test objspace objspace/flow objspace/std objspace/std/test Message-ID: <20100607180358.3B176282BDB@codespeak.net> Author: benjamin Date: Mon Jun 7 20:03:54 2010 New Revision: 75180 Added: pypy/branch/fast-forward/pypy/objspace/std/newformat.py (contents, props changed) pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py (contents, props changed) Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py pypy/branch/fast-forward/pypy/module/__builtin__/operation.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py pypy/branch/fast-forward/pypy/objspace/descroperation.py pypy/branch/fast-forward/pypy/objspace/flow/operation.py pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py pypy/branch/fast-forward/pypy/objspace/std/default.py pypy/branch/fast-forward/pypy/objspace/std/intobject.py pypy/branch/fast-forward/pypy/objspace/std/longobject.py pypy/branch/fast-forward/pypy/objspace/std/stringobject.py pypy/branch/fast-forward/pypy/objspace/std/stringtype.py pypy/branch/fast-forward/pypy/objspace/std/unicodeobject.py pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py Log: implement advanced string formatting - add space.format() and a format() builtin - add unicode/str format() method - implement formatting for integers and string Floats, complex, and locale aware formatting will follow. Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Mon Jun 7 20:03:54 2010 @@ -1205,6 +1205,7 @@ ('issubtype', 'issubtype', 2, []), # not for old-style classes ('repr', 'repr', 1, ['__repr__']), ('str', 'str', 1, ['__str__']), + ('format', 'format', 2, ['__format__']), ('len', 'len', 1, ['__len__']), ('hash', 'hash', 1, ['__hash__']), ('getattr', 'getattr', 2, ['__getattribute__']), Modified: pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py Mon Jun 7 20:03:54 2010 @@ -6,9 +6,9 @@ # put builtins here that should be optimized somehow OPTIMIZED_BUILTINS = ["len", "range", "xrange", "min", "max", "enumerate", - "isinstance", "type", "zip", "file", "open", "abs", "chr", "unichr", - "ord", "pow", "repr", "hash", "oct", "hex", "round", "cmp", "getattr", - "setattr", "delattr", "callable", "int", "str", "float"] + "isinstance", "type", "zip", "file", "format", "open", "abs", "chr", + "unichr", "ord", "pow", "repr", "hash", "oct", "hex", "round", "cmp", + "getattr", "setattr", "delattr", "callable", "int", "str", "float"] assert len(OPTIMIZED_BUILTINS) <= 256 @@ -72,6 +72,7 @@ 'cmp' : 'operation.cmp', 'coerce' : 'operation.coerce', 'divmod' : 'operation.divmod', + 'format' : 'operation.format', '_issubtype' : 'operation._issubtype', 'issubclass' : 'abstractinst.app_issubclass', 'isinstance' : 'abstractinst.app_isinstance', Modified: pypy/branch/fast-forward/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/operation.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/operation.py Mon Jun 7 20:03:54 2010 @@ -221,3 +221,8 @@ function). Note that classes are callable.""" return space.callable(w_object) +def format(space, w_obj, w_format_spec=NoneNotWrapped): + """Format a obj according to format_spec""" + if w_format_spec is None: + w_format_spec = space.wrap("") + return space.format(w_obj, w_format_spec) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Mon Jun 7 20:03:54 2010 @@ -97,6 +97,13 @@ return 'a' # not a list! raises(TypeError, eval, "dir()", {}, C()) + def test_format(self): + assert format(4) == "4" + assert format(10, "o") == "12" + assert format(10, "#o") == "0o12" + assert format("hi") == "hi" + assert isinstance(format(4, u""), unicode) + def test_vars(self): def f(): return vars() Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/descroperation.py Mon Jun 7 20:03:54 2010 @@ -312,6 +312,15 @@ w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop) return space.get_and_call_function(w_descr, w_obj, w_start, w_stop) + def format(space, w_obj, w_format_spec): + w_descr = space.lookup(w_obj, '__format__') + if w_descr is None: + typename = space.type(w_obj).getname(space, '?') + raise operationerrfmt(space.w_TypeError, + "'%s' object does not define __format__", + typename) + return space.get_and_call_function(w_descr, w_obj, w_format_spec) + def pow(space, w_obj1, w_obj2, w_obj3): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) Modified: pypy/branch/fast-forward/pypy/objspace/flow/operation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/flow/operation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/flow/operation.py Mon Jun 7 20:03:54 2010 @@ -159,6 +159,9 @@ def do_delslice(a, b, c): del a[b:c] +def unsupported(*args): + raise ValueError("this is not supported") + # ____________________________________________________________ # The following table can list several times the same operation name, @@ -174,6 +177,7 @@ ('issubtype', issubclass), ('repr', repr), ('str', str), + ('format', unsupported), ('len', len), ('hash', hash), ('getattr', getattr), Modified: pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py Mon Jun 7 20:03:54 2010 @@ -27,6 +27,8 @@ 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow', 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or', 'inplace_xor', + # other + 'format', ]) KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD Modified: pypy/branch/fast-forward/pypy/objspace/std/default.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/default.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/default.py Mon Jun 7 20:03:54 2010 @@ -45,4 +45,14 @@ raise OperationError(space.w_TypeError, typed_unwrap_error_msg(space, "integer", w_obj)) +def format__ANY_ANY(space, w_obj, w_format_spec): + if space.isinstance_w(w_format_spec, space.w_unicode): + w_as_str = space.unicode(w_obj) + elif space.isinstance_w(w_format_spec, space.w_str): + w_as_str = space.str(w_obj) + else: + msg = "format_spec must be a string" + raise OperationError(space.w_TypeError, space.wrap(msg)) + return space.format(w_as_str) + register_all(vars()) Modified: pypy/branch/fast-forward/pypy/objspace/std/intobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/intobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/intobject.py Mon Jun 7 20:03:54 2010 @@ -1,4 +1,5 @@ from pypy.interpreter.error import OperationError +from pypy.objspace.std import newformat from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.multimethod import FailedToImplementArgs @@ -60,6 +61,10 @@ str__Int = repr__Int +def format__Int_ANY(space, w_int, w_format_spec): + form = newformat.get_formatter(space, w_format_spec) + return form.format_int_or_long(w_int, newformat.INT_KIND) + def declare_new_int_comparison(opname): import operator from pypy.tool.sourcetools import func_with_new_name Modified: pypy/branch/fast-forward/pypy/objspace/std/longobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/longobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/longobject.py Mon Jun 7 20:03:54 2010 @@ -1,6 +1,6 @@ import sys from pypy.interpreter.error import OperationError -from pypy.objspace.std import model +from pypy.objspace.std import model, newformat from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.multimethod import FailedToImplementArgs @@ -124,6 +124,10 @@ def str__Long(space, w_long): return space.wrap(w_long.num.str()) +def format__Long_ANY(space, w_long, w_format_spec): + formatter = newformat.get_formatter(space, w_format_spec) + return formatter.format_int_or_long(w_long, newformat.LONG_KIND) + def lt__Long_Long(space, w_long1, w_long2): return space.newbool(w_long1.num.lt(w_long2.num)) Added: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- (empty file) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Mon Jun 7 20:03:54 2010 @@ -0,0 +1,694 @@ +"""The unicode/str format() method""" + +import string + +from pypy.interpreter.error import OperationError +from pypy.rlib import rstring, runicode +from pypy.rlib.objectmodel import specialize + + +# Auto number state +ANS_INIT = 1 +ANS_AUTO = 2 +ANS_MANUAL = 3 + + +class TemplateFormatter(object): + + _annspecialcase_ = "specialize:ctr_location" + + def __init__(self, space, is_unicode, template): + self.space = space + self.is_unicode = is_unicode + self.empty = u"" if is_unicode else "" + self.template = template + + def build(self, args): + self.args, self.kwargs = args.unpack() + self.auto_numbering = 0 + self.auto_numbering_state = ANS_INIT + return self._build_string(0, len(self.template), 2) + + def _build_string(self, start, end, level): + space = self.space + if self.is_unicode: + out = rstring.UnicodeBuilder() + else: + out = rstring.StringBuilder() + if not level: + raise OperationError(space.w_ValueError, + space.wrap("Recursion depth exceeded")) + level -= 1 + s = self.template + last_literal = i = start + while i < end: + c = s[i] + i += 1 + if c == "{" or c == "}": + at_end = i == end + # Find escaped "{" and "}" + markup_follows = True + if c == "}": + if at_end or s[i] != "}": + raise OperationError(space.w_ValueError, + space.wrap("Single '}'")) + i += 1 + markup_follows = False + if c == "{": + if at_end: + raise OperationError(space.w_ValueError, + space.wrap("Single '{'")) + if s[i] == "{": + i += 1 + markup_follows = False + # Attach literal data + out.append_slice(s, last_literal, i - 1) + if not markup_follows: + last_literal = i + continue + nested = 1 + field_start = i + recursive = False + while i < end: + c = s[i] + if c == "{": + recursive = True + nested += 1 + elif c == "}": + nested -= 1 + if not nested: + break + i += 1 + if nested: + raise OperationError(space.w_ValueError, + space.wrap("Unmatched '{'")) + rendered = self._render_field(field_start, i, recursive, level) + out.append(rendered) + i += 1 + last_literal = i + + out.append_slice(s, last_literal, end) + return out.build() + + def _parse_field(self, start, end): + s = self.template + # Find ":" or "!" + i = start + while i < end: + c = s[i] + if c == ":" or c == "!": + end_name = i + if c == "!": + i += 1 + if i == end: + raise OperationError(space.w_ValueError, + space.wrap("expected conversion")) + conversion = s[i] + else: + conversion = None + i += 1 + return s[start:end_name], conversion, i + i += 1 + return s[start:end], self.empty, end + + def _get_argument(self, name): + # First, find the argument. + space = self.space + i = 0 + end = len(name) + while i < end: + c = name[i] + if c == "[" or c == ".": + break + i += 1 + arg_ref = name[:i] + try: + index = int(arg_ref) + except ValueError: + index = -1 + empty = not i + use_numeric = empty or index != -1 + if self.auto_numbering_state == ANS_INIT and use_numeric: + if empty: + self.auto_numbering_state = ANS_AUTO + else: + self.auto_numbering_state = ANS_MANUAL + if use_numeric: + if self.auto_numbering_state == ANS_MANUAL: + if empty: + msg = "switching from manual to automatic numbering" + raise OperationError(space.w_ValueError, + space.wrap(msg)) + elif not empty: + msg = "switching from automatic to manual numbering" + raise OperationError(space.w_ValueError, + space.wrap(msg)) + if empty: + index = self.auto_numbering + self.auto_numbering += 1 + if index == -1: + try: + w_arg = self.kwargs[arg_ref] + except KeyError: + raise OperationError(space.w_KeyError, space.wrap(arg_ref)) + else: + try: + w_arg = self.args[index] + except IndexError: + w_msg = space.wrap("index out of range") + raise OperationError(space.w_IndexError, w_msg) + # Resolve attribute and item lookups. + w_obj = w_arg + is_attribute = False + while i < end: + c = name[i] + if c == ".": + i += 1 + start = i + while i < end: + c = name[i] + if c == "[" or c == ".": + break + i += 1 + w_obj = space.getattr(w_obj, space.wrap(name[start:i])) + elif c == "[": + got_bracket = False + i += 1 + start = i + while i < end: + c = name[i] + if c == "]": + got_bracket = True + break + i += 1 + if not got_bracket: + raise OperationError(space.w_ValueError, + space.wrap("Missing ']'")) + item = name[start:i] + i += 1 # Skip "]" + try: + index = int(item) + except ValueError: + w_item = space.wrap(item) + else: + w_item = space.wrap(index) + w_obj = space.getitem(w_obj, w_item) + else: + msg = "Only '[' and '.' may follow ']'" + raise OperationError(space.w_ValueError, space.wrap(msg)) + return w_obj + + def _convert(self, w_obj, conversion): + space = self.space + if conversion == "r": + return space.repr(w_obj) + elif conversion == "s": + if self.is_unicode: + return space.call_function(space.w_unicode, w_obj) + return space.str(w_obj) + else: + raise OperationError(self.space.w_ValueError, + self.space.wrap("invalid conversion")) + + def _render_field(self, start, end, recursive, level): + name, conversion, spec_start = self._parse_field(start, end) + spec = self.template[spec_start:end] + w_obj = self._get_argument(name) + if conversion: + w_obj = self._convert(w_obj, conversion) + if recursive: + spec = self._build_string(spec_start, end, level) + w_rendered = self.space.format(w_obj, self.space.wrap(spec)) + unwrapper = "unicode_w" if self.is_unicode else "str_w" + to_interp = getattr(self.space, unwrapper) + return to_interp(w_rendered) + + +def format_method(space, w_string, args, is_unicode): + if is_unicode: + template = TemplateFormatter(space, True, space.unicode_w(w_string)) + return space.wrap(template.build(args)) + else: + template = TemplateFormatter(space, False, space.str_w(w_string)) + return space.wrap(template.build(args)) + + +class NumberSpec(object): + pass + +class BaseFormatter(object): + pass + +INT_KIND = 1 +LONG_KIND = 2 + +NO_LOCALE = 1 +DEFAULT_LOCALE = 2 +CURRENT_LOCALE = 3 + +LONG_DIGITS = string.digits + string.ascii_lowercase + +class Formatter(BaseFormatter): + """__format__ implementation for builtin types.""" + + _annspecialcase_ = "specialize:ctr_location" + + def __init__(self, space, is_unicode, spec): + self.space = space + self.is_unicode = is_unicode + self.empty = u"" if is_unicode else "" + self.spec = spec + + def _is_alignment(self, c): + return (c == "<" or + c == ">" or + c == "=" or + c == "^") + + def _is_sign(self, c): + return (c == " " or + c == "+" or + c == "-") + + def _get_integer(self, spec, i, length): + start_width = i + while i < length: + char_index = ord(spec[i]) + if char_index < ord("0") or ord("9") < char_index: + break + i += 1 + num = int(spec[start_width:i]) if start_width != i else -1 + return num, i + + def _parse_spec(self, default_type, default_align): + space = self.space + self._fill_char = "\0" + self._align = default_align + self._alternate = False + self._sign = "\0" + self._thousands_sep = False + self._precision = -1 + self._type = default_type + spec = self.spec + if not spec: + return True + length = len(spec) + i = 0 + got_align = True + if length - i >= 2 and self._is_alignment(spec[i + 1]): + self._align = spec[i + 1] + self._fill_char = spec[i] + i += 2 + elif length - i >= 1 and self._is_alignment(spec[i]): + self._align = spec[i] + i += 1 + else: + got_align = False + if length - i >= 1 and self._is_sign(spec[i]): + self._sign = spec[i] + i += 1 + if length - i >= 1 and spec[i] == "#": + self._alternate = True + i += 1 + if self._fill_char == "\0" and length - i >= 1 and spec[i] == "0": + self._fill_char = "0" + if not got_align: + self._align = "=" + i += 1 + self._width, i = self._get_integer(spec, i, length) + if length - i and spec[i] == ",": + self._thousands_sep = True + i += 1 + if length - i and spec[i] == ".": + i += 1 + self._precision, i = self._get_integer(spec, i, length) + if self._precision == -1: + raise OperationError(space.w_ValueError, + space.wrap("no precision given")) + if length - i > 1: + raise OperationError(space.w_ValueError, + space.wrap("invalid format spec")) + if length - i == 1: + self._type = spec[i] + i += 1 + if self._thousands_sep: + tp = self._type + if (tp == "d" or + tp == "e" or + tp == "f" or + tp == "g" or + tp == "E" or + tp == "G" or + tp == "%" or + tp == "F" or + tp == "\0"): + # ok + pass + else: + raise OperationError(space.w_ValueError, + space.wrap("invalid type with ','")) + return False + + def _calc_padding(self, string, length): + if self._width != -1 and length < self._width: + total = self._width + else: + total = length + align = self._align + if align == ">": + left = total - length + elif align == "^": + left = (total - length) / 2 + elif align == "<" or align == "=": + left = 0 + else: + raise AssertionError("shouldn't be here") + right = total - length - left + self._left_pad = left + self._right_pad = right + return total + + def _pad(self, string): + builder = self._builder() + builder.append_multiple_char(self._fill_char, self._left_pad) + builder.append(string) + builder.append_multiple_char(self._fill_char, self._right_pad) + return builder.build() + + def _builder(self): + if self.is_unicode: + return rstring.UnicodeBuilder() + else: + return rstring.StringBuilder() + + def _unknown_presentation(self, tp): + msg = "unknown presentation for %s: '%s'" % (tp, self._type) + raise OperationError(self.space.w_ValueError, self.space.wrap(msg)) + + def format_string(self, string): + space = self.space + if self._parse_spec("s", "<"): + return space.wrap(string) + if self._type != "s": + self._unknown_presentation("string") + if self._sign != "\0": + msg = "Sign not allowed in string format specifier" + raise OperationError(space.w_ValueError, space.wrap(msg)) + if self._alternate: + msg = "Alternate form not allowed in string format specifier" + raise OperationError(space.w_ValueError, space.wrap(msg)) + if self._align == "=": + msg = "'=' alignment not allowed in string format specifier" + raise OperationError(space.w_ValueError, space.wrap(msg)) + length = len(string) + if self._precision != -1 and length >= self._precision: + length = self._precision + if self._fill_char == "\0": + self._fill_char = " " + self._calc_padding(string, length) + return space.wrap(self._pad(string)) + + def _get_locale(self, locale_kind): + space = self.space + if locale_kind == CURRENT_LOCALE: + _locale = space.getbuiltnmodule("_locale") + w_lconv = space.call_method(_locale, "localeconv") + w = space.wrap + dec = space.str_w(space.getitem(w_lconv, w("decimal_point"))) + thousands = space.str_w(space.getitem(w_lconv, w("thousands_sep"))) + grouping = space.str_w(space.getitem(w_lconv, w("grouping"))) + elif locale_kind == DEFAULT_LOCALE: + dec = "." + thousands = "," + grouping = "\3" + elif locale_kind == NO_LOCALE: + dec = "." + thousands = "" + grouping = "\256" + if self.is_unicode: + self._loc_dec = dec.decode("ascii") + self._loc_thousands = thousands.decode("ascii") + else: + self._loc_dec = dec + self._loc_thousands = thousands + self._loc_grouping = grouping + + def _calc_num_width(self, n_prefix, sign_char, to_number, n_number, + n_remainder, has_dec): + spec = NumberSpec() + spec.n_digits = n_number - n_remainder - has_dec + spec.n_prefix = n_prefix + spec.n_lpadding = 0 + spec.n_decimal = 1 if has_dec else 0 + spec.n_remainder = n_remainder + spec.n_spadding = 0 + spec.n_rpadding = 0 + spec.sign = "\0" + spec.n_sign = 0 + sign = self._sign + if sign == "+": + spec.n_sign = 1 + spec.sign = "-" if sign_char == "-" else "+" + elif sign == " ": + spec.n_sign = 1 + spec.sign = "-" if sign_char == "-" else " " + elif sign_char == "-": + spec.n_sign = 1 + spec.sign = "-" + extra_length = (spec.n_sign + spec.n_prefix + spec.n_decimal + + spec.n_remainder) # Not padding or digits + if self._fill_char == "0" and self._align == "=": + spec.n_min_width = self._width - extra_length + n_padding = self._width - (extra_length + spec.n_digits) + if n_padding > 0: + align = self._align + if align == "<": + spec.n_rpadding = n_padding + elif align == ">": + spec.n_lpadding = n_padding + elif align == "^": + spec.n_lpadding = n_padding // 2 + spec.n_rpadding = n_padding - spec.n_lpadding + elif align == "=": + spec.n_spadding = n_padding + else: + raise AssertionError("shouldn't reach") + return spec + + def _upcase_string(self, s): + buf = [] + for c in s: + index = ord(c) + if ord("a") <= index <= ord("z"): + c = chr(index - 32) + buf.append(c) + return self.empty.join(buf) + + + def _fill_number(self, spec, num, to_digits, n_digits, to_prefix, fill_char, + upper): + out = self._builder() + if spec.n_lpadding: + out.append_multiple_char(fill_char, spec.n_lpadding) + if spec.n_sign: + out.append(spec.sign) + if spec.n_prefix: + pref = num[to_prefix:to_prefix + spec.n_prefix] + if upper: + pref = self._upcase_string(pref) + out.append(pref) + if spec.n_spadding: + out.append_multiple_char(fill_char, spec.n_spadding) + if spec.n_digits != 0: + num = num[to_digits:] + if upper: + num = self._upcase_string(num) + out.append(num) + if spec.n_decimal: + out.append(".") + if spec.n_remainder: + out.append(num[0]) + if spec.n_rpadding: + out.append_multiple_char(fill_char, spec.n_rpadding) + return self.space.wrap(out.build()) + + def _format_int_or_long(self, w_num, kind): + space = self.space + if self._precision != -1: + msg = "precision not allowed in integer type" + raise OperationError(space.w_ValueError, space.wrap(msg)) + sign_char = "\0" + tp = self._type + if tp == "c": + if self._sign != "\0": + msg = "sign not allowed with 'c' presentation type" + raise OperationError(space.w_ValueError, space.wrap(msg)) + if self._thousands_sep: + msg = "thousands separator not allowed with 'c' presentation" + raise Operationerror(space.w_ValueError, space.wrap(msg)) + value = space.int_w(w_num) + if self.is_unicode: + result = runicode.UNICHR(value) + else: + result = chr(value) + n_digits = 1 + n_remainder = 1 + n_prefix = 0 + to_prefix = 0 + to_numeric = 0 + else: + if tp == "b": + base = 2 + skip_leading = 2 + elif tp == "o": + base = 8 + skip_leading = 2 + elif tp == "x" or tp == "X": + base = 16 + skip_leading = 2 + elif tp == "n" or tp == "d": + base = 10 + skip_leading = 0 + else: + raise AssertionError("shouldn't reach") + if kind == INT_KIND: + result = self._int_to_base(base, space.int_w(w_num)) + else: + result = self._long_to_base(base, space.bigint_w(w_num)) + n_prefix = skip_leading if self._alternate else 0 + to_prefix = 0 + if result[0] == "-": + sign_char = "-" + skip_leading += 1 + to_prefix += 1 + n_digits = len(result) - skip_leading + n_remainder = 0 + to_numeric = skip_leading + spec = self._calc_num_width(n_prefix, sign_char, to_numeric, n_digits, + n_remainder, False) + fill = " " if self._fill_char == "\0" else self._fill_char + upper = self._type == "X" + return self._fill_number(spec, result, to_numeric, n_digits, to_prefix, + fill, upper) + + def _long_to_base(self, base, value): + prefix = "" + if base == 2: + prefix = "0b" + elif base == 8: + prefix = "0o" + elif base == 16: + prefix = "0x" + as_str = value.format(LONG_DIGITS[:base], prefix) + if self.is_unicode: + return as_str.decode("ascii") + return as_str + + def _int_to_base(self, base, value): + if base == 10: + return unicode(value) if self.is_unicode else str(value) + # This part is slow. + negative = value < 0 + value = abs(value) + buf = ["\0"] * (8 * 8 + 6) # Too much on 32 bit, but who cares? + i = len(buf) - 1 + while True: + div = value // base + mod = value - div * base + digit = abs(mod) + digit += ord("0") if digit < 10 else ord("a") - 10 + buf[i] = chr(digit) + value = div + i -= 1 + if not value: + break + if base == 2: + buf[i] = "b" + buf[i - 1] = "0" + elif base == 8: + buf[i] = "o" + buf[i - 1] = "0" + elif base == 16: + buf[i] = "x" + buf[i - 1] = "0" + else: + buf[i] = "#" + buf[i - 1] = chr(ord("0") + base % 10) + if base > 10: + buf[i - 2] = chr(ord("0") + base // 10) + i -= 1 + i -= 1 + if negative: + i -= 1 + buf[i] = "-" + return self.empty.join(buf[i:]) + + def format_int_or_long(self, w_num, kind): + space = self.space + if self._parse_spec("d", ">"): + if self.is_unicode: + return space.call_function(space.w_unicode, w_num) + return self.space.str(w_num) + tp = self._type + if (tp == "b" or + tp == "c" or + tp == "d" or + tp == "o" or + tp == "x" or + tp == "X" or + tp == "n"): + return self._format_int_or_long(w_num, kind) + elif (tp == "e" or + tp == "E" or + tp == "f" or + tp == "F" or + tp == "g" or + tp == "G" or + tp == "%"): + w_float = space.float(w_num) + self._format_float(w_float) + else: + self._unknown_presentation("int" if kind == INT_KIND else "long") + + def _format_float(self, w_float): + space = self.space + if self._alternate: + msg = "alternate form not allowed in float formats" + raise OperationError(space.w_ValueError, space.wrap(msg)) + tp = self._type + if tp == "\0": + tp = "g" + + def format_float(self, w_float): + space = self.space + if self._parse_spec("\0", ">"): + if self.is_unicode: + return space.call_function(space.w_unicode, w_float) + return space.str(w_float) + tp = self._type + if (tp == "\0" or + tp == "e" or + tp == "E" or + tp == "f" or + tp == "F" or + tp == "g" or + tp == "G" or + tp == "n" or + tp == "%"): + return self._format_float(w_float) + self._unknown_presentation("float") + + +def unicode_formatter(space, spec): + return Formatter(space, True, spec) + + +def str_formatter(space, spec): + return Formatter(space, False, spec) + + +def get_formatter(space, w_format_spec): + if space.isinstance_w(w_format_spec, space.w_unicode): + return unicode_formatter(space, space.unicode_w(w_format_spec)) + else: + return str_formatter(space, space.str_w(w_format_spec)) Modified: pypy/branch/fast-forward/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/stringobject.py Mon Jun 7 20:03:54 2010 @@ -7,7 +7,7 @@ from pypy.rlib.objectmodel import we_are_translated, compute_hash 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 slicetype, newformat from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.tupleobject import W_TupleObject @@ -963,6 +963,16 @@ def mod__String_ANY(space, w_format, w_values): return mod_format(space, w_format, w_values, do_unicode=False) +def str_format__String(space, w_string, __args__): + return newformat.format_method(space, w_string, __args__, False) + +def format__String_ANY(space, w_string, w_format_spec): + if not space.isinstance_w(w_format_spec, space.w_str): + w_format_spec = space.str(w_format_spec) + spec = space.str_w(w_format_spec) + formatter = newformat.str_formatter(space, spec) + return formatter.format_string(w_string._value) + def buffer__String(space, w_string): from pypy.interpreter.buffer import StringBuffer return space.wrap(StringBuffer(w_string._value)) Modified: pypy/branch/fast-forward/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/stringtype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/stringtype.py Mon Jun 7 20:03:54 2010 @@ -88,6 +88,7 @@ ' maxsplit is given, at most maxsplit splits are\ndone.' ' If sep is not specified or is None, any whitespace' ' string\nis a separator.') +str_format = SMM('format', 1, general__args__=True) str_isdigit = SMM('isdigit', 1, doc='S.isdigit() -> bool\n\nReturn True if all characters' ' in S are digits\nand there is at least one' Added: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py ============================================================================== --- (empty file) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Mon Jun 7 20:03:54 2010 @@ -0,0 +1,199 @@ +"""Test unicode/str's format method""" + + +class BaseStringFormatTests: + """Test format and __format__ methods of string objects.""" + + def test_escape(self): + assert self.s("{{").format() == self.s("{") + assert self.s("}}").format() == self.s("}") + assert self.s("{} {{ {}").format(1, 2) == self.s("1 { 2") + assert self.s("{{}}").format() == self.s("{}") + + def test_empty(self): + assert self.s().format() == self.s() + assert self.s("x").format() == self.s("x") + + def test_several(self): + res = self.s("x32 stuff 42m") + assert self.s("x{} stuff {}m").format(32, 42) == res + + def test_stray_brackets(self): + raises(ValueError, self.s("}").format, 3) + raises(ValueError, self.s("{").format, 3) + raises(ValueError, self.s("{}}").format, 3) + + def test_auto_numbering(self): + res = "1 3 2" + assert self.s("{} {name} {}").format(1, 2, name=3) == self.s(res) + raises(ValueError, self.s("{} {2}").format, 2, 3) + raises(ValueError, self.s("{0} {}").format, 2, 3) + + def test_positional_args(self): + assert self.s("{1}{0}").format(2, 3) == self.s("32") + raises(IndexError, self.s("{2}").format, 2) + + def test_kwargs(self): + assert self.s("{what}").format(what=42) == self.s("42") + raises(KeyError, self.s("{nothing}").format) + + def test_attr(self): + class x: + apple = 42 + assert self.s("{.apple}").format(x) == self.s("42") + + def test_index(self): + seq = (1, 42) + assert self.s("{[1]}").format(seq) == self.s("42") + + def test_getitem(self): + d = {"hi" : 32} + assert self.s("{[hi]}").format(d) == self.s("32") + + def test_chained(self): + class x: + y = [1, 2, 3] + assert self.s("{.y[1]}").format(x) == self.s("2") + l = [1, x] + assert self.s("{[1].y[2]}").format(l) == self.s("3") + + def test_invalid_field_name(self): + raises(ValueError, self.s("{[x]y}").format, {"x" : 2}) + + def test_repr_conversion(self): + class x(object): + def __repr__(self): + return "32" + assert self.s("{!r}").format(x()) == self.s("32") + assert self.s("{!s}").format(x()) == self.s("32") + + def test_invalid_conversion(self): + raises(ValueError, self.s("{!x}").format, 3) + + def test_recursive(self): + assert self.s("{:{}}").format(42, "#o") == self.s("0o52") + raises(ValueError, self.s("{{}:s}").format) + raises(ValueError, self.s("{:{:{}}}").format, 1, 2, 3) + + def test_presentation(self): + assert format(self.s("blah"), "s") == self.s("blah") + assert format(self.s("blah")) == self.s("blah") + for pres in "bcdoxXeEfFgGn%": + raises(ValueError, format, self.s("blah"), pres) + + def test_padding(self): + assert format(self.s("h"), "3") == self.s("h ") + assert format(self.s("h"), "<3") == self.s("h ") + assert format(self.s("h"), ">3") == self.s(" h") + assert format(self.s("h"), "^3") == self.s(" h ") + assert format(self.s("h"), "^4") == self.s(" h ") + assert format(self.s("h"), "c<3") == self.s("hcc") + raises(ValueError, format, self.s("blah"), "=12") + + +class AppTestUnicodeFormat(BaseStringFormatTests): + + def setup_class(cls): + cls.w_s = cls.space.w_unicode + + def test_string_conversion(self): + class x(object): + def __repr__(self): + return "32" + def __str__(self): + return "18" + def __unicode__(self): + return "42" + assert self.s("{!s}").format(x()) == self.s("42") + assert self.s("{!r}").format(x()) == self.s("32") + + +class AppTestStringFormat(BaseStringFormatTests): + + def setup_class(cls): + cls.w_s = cls.space.w_str + + def test_string_conversion(self): + class x(object): + def __repr__(self): + return "32" + def __str__(self): + return "18" + def __unicode__(self): + return "42" + assert self.s("{!s}").format(x()) == self.s("18") + assert self.s("{!r}").format(x()) == self.s("32") + + +class BaseIntegralFormattingTest: + + def test_simple(self): + assert format(self.i(2)) == "2" + assert isinstance(format(self.i(2), u""), unicode) + + def test_invalid(self): + raises(ValueError, format, self.i(8), "s") + raises(ValueError, format, self.i(8), ".3") + + def test_c(self): + a = self.i(ord("a")) + assert format(a, "c") == "a" + as_uni = format(a, u"c") + assert as_uni == u"a" + assert isinstance(as_uni, unicode) + raises(ValueError, format, a, "-c") + raises(ValueError, format, a, ",c") + assert format(a, "3c") == " a" + assert format(a, "<3c") == "a " + assert format(a, "^3c") == " a " + assert format(a, "=3c") == " a" + assert format(a, "x^3c") == "xax" + + def test_binary(self): + assert format(self.i(2), "b") == "10" + assert format(self.i(2), "#b") == "0b10" + + def test_octal(self): + assert format(self.i(8), "o") == "10" + assert format(self.i(8), "#o") == "0o10" + assert format(self.i(-8), "o") == "-10" + assert format(self.i(-8), "#o") == "-0o10" + assert format(self.i(8), "+o") == "+10" + assert format(self.i(8), "+#o") == "+0o10" + + def test_hex(self): + assert format(self.i(16), "x") == "10" + assert format(self.i(16), "#x") == "0x10" + assert format(self.i(10), "x") == "a" + assert format(self.i(10), "#x") == "0xa" + assert format(self.i(10), "X") == "A" + assert format(self.i(10), "#X") == "0XA" + + def test_padding(self): + assert format(self.i(6), "3") == " 6" + assert format(self.i(6), ">3") == " 6" + assert format(self.i(6), "<3") == "6 " + assert format(self.i(6), "=3") == " 6" + assert format(self.i(6), "=+3") == "+ 6" + assert format(self.i(6), "a^3") == "a6a" + + def test_sign(self): + assert format(self.i(-6)) == "-6" + assert format(self.i(-6), "-") == "-6" + assert format(self.i(-6), "+") == "-6" + assert format(self.i(-6), " ") == "-6" + assert format(self.i(6), " ") == " 6" + assert format(self.i(6), "-") == "6" + assert format(self.i(6), "+") == "+6" + + +class AppTestIntFormatting(BaseIntegralFormattingTest): + + def setup_class(cls): + cls.w_i = cls.space.w_int + + +class AppTestLongFormatting(BaseIntegralFormattingTest): + + def setup_class(cls): + cls.w_i = cls.space.w_long Modified: pypy/branch/fast-forward/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/unicodeobject.py Mon Jun 7 20:03:54 2010 @@ -7,7 +7,7 @@ from pypy.objspace.std.ropeobject import W_RopeObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice -from pypy.objspace.std import slicetype +from pypy.objspace.std import slicetype, newformat from pypy.objspace.std.tupleobject import W_TupleObject from pypy.rlib.rarithmetic import intmask, ovfcheck from pypy.rlib.objectmodel import compute_hash @@ -991,6 +991,16 @@ def mod__Unicode_ANY(space, w_format, w_values): return mod_format(space, w_format, w_values, do_unicode=True) +def unicode_format__Unicode(space, w_unicode, __args__): + return newformat.format_method(space, w_unicode, __args__, True) + +def format__Unicode_ANY(space, w_unicode, w_format_spec): + if not space.isinstance_w(w_format_spec, space.w_unicode): + w_format_spec = space.call_function(space.w_unicode, w_format_spec) + spec = space.unicode_w(w_format_spec) + formatter = newformat.unicode_formatter(space, spec) + return formatter.format_string(w_unicode._value) + def buffer__Unicode(space, w_unicode): from pypy.rlib.rstruct.unichar import pack_unichar charlist = [] Modified: pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py Mon Jun 7 20:03:54 2010 @@ -62,6 +62,8 @@ ' copy of S where all tab characters are expanded' ' using spaces.\nIf tabsize is not given, a tab' ' size of 8 characters is assumed.') +unicode_format = SMM('format', 1, general__args__=True, + doc='S.format() -> new style formating') unicode_isalnum = SMM('isalnum', 1, doc='S.isalnum() -> bool\n\nReturn True if all' ' characters in S are alphanumeric\nand there is' From benjamin at codespeak.net Mon Jun 7 20:16:25 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 7 Jun 2010 20:16:25 +0200 (CEST) Subject: [pypy-svn] r75181 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100607181625.E2C75282BDB@codespeak.net> Author: benjamin Date: Mon Jun 7 20:16:23 2010 New Revision: 75181 Modified: pypy/branch/fast-forward/pypy/objspace/std/default.py pypy/branch/fast-forward/pypy/objspace/std/objecttype.py pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py Log: add default __format__ to object Modified: pypy/branch/fast-forward/pypy/objspace/std/default.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/default.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/default.py Mon Jun 7 20:16:23 2010 @@ -45,14 +45,4 @@ raise OperationError(space.w_TypeError, typed_unwrap_error_msg(space, "integer", w_obj)) -def format__ANY_ANY(space, w_obj, w_format_spec): - if space.isinstance_w(w_format_spec, space.w_unicode): - w_as_str = space.unicode(w_obj) - elif space.isinstance_w(w_format_spec, space.w_str): - w_as_str = space.str(w_obj) - else: - msg = "format_spec must be a string" - raise OperationError(space.w_TypeError, space.wrap(msg)) - return space.format(w_as_str) - register_all(vars()) Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/objecttype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/objecttype.py Mon Jun 7 20:16:23 2010 @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.typedef import GetSetProperty, default_identity_hash from pypy.interpreter import gateway +from pypy.interpreter.baseobjspace import ObjSpace from pypy.objspace.descroperation import Object from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr from pypy.objspace.std.register_all import register_all @@ -89,6 +90,17 @@ return space.call(w_reduce, space.newtuple([])) return descr__reduce__(space, w_obj, proto) +def descr___format__(space, w_obj, w_format_spec): + if space.isinstance_w(w_format_spec, space.w_unicode): + w_as_str = space.call_function(space.w_unicode, w_obj) + elif space.isinstance_w(w_format_spec, space.w_str): + w_as_str = space.str(w_obj) + else: + msg = "format_spec must be a string" + raise OperationError(space.w_TypeError, space.wrap(msg)) + return space.format(w_as_str, w_format_spec) + + app = gateway.applevel(r''' def reduce_1(obj, proto): import copy_reg @@ -177,6 +189,8 @@ unwrap_spec=[gateway.ObjSpace,gateway.W_Root,int]), __reduce__ = gateway.interp2app(descr__reduce__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,int]), + __format__ = gateway.interp2app(descr___format__, unwrap_spec=[ObjSpace, + gateway.W_Root, gateway.W_Root]), __init__ = gateway.interp2app(descr__init__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), ) Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py Mon Jun 7 20:16:23 2010 @@ -46,3 +46,20 @@ return object.__reduce__(self) + (':-)',) s = X().__reduce__() assert s[-1] == ':-)' + + def test_default_format(self): + class x(object): + def __str__(self): + return "Pickle" + def __unicode__(self): + return u"Cheese" + res = format(x()) + assert res == "Pickle" + assert isinstance(res, str) + res = format(x(), u"") + assert res == u"Cheese" + assert isinstance(res, unicode) + del x.__unicode__ + res = format(x(), u"") + assert res == u"Pickle" + assert isinstance(res, unicode) From benjamin at codespeak.net Mon Jun 7 20:22:38 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 7 Jun 2010 20:22:38 +0200 (CEST) Subject: [pypy-svn] r75182 - in pypy/branch/fast-forward: . lib-python py/_code pypy/annotation pypy/annotation/test pypy/doc pypy/jit/metainterp pypy/jit/metainterp/test pypy/module/_codecs pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/patches pypy/module/cpyext/test pypy/module/imp pypy/module/imp/test pypy/module/sys pypy/objspace/std pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/test pypy/tool/pytest pypy/tool/pytest/test Message-ID: <20100607182238.8D8A9282BDB@codespeak.net> Author: benjamin Date: Mon Jun 7 20:22:34 2010 New Revision: 75182 Added: pypy/branch/fast-forward/pypy/module/cpyext/test/test_translate.py - copied unchanged from r75181, pypy/trunk/pypy/module/cpyext/test/test_translate.py Modified: pypy/branch/fast-forward/ (props changed) pypy/branch/fast-forward/lib-python/conftest.py pypy/branch/fast-forward/py/_code/source.py pypy/branch/fast-forward/pypy/annotation/binaryop.py pypy/branch/fast-forward/pypy/annotation/builtin.py pypy/branch/fast-forward/pypy/annotation/classdef.py pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py pypy/branch/fast-forward/pypy/doc/objspace.txt pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py pypy/branch/fast-forward/pypy/module/_codecs/interp_codecs.py pypy/branch/fast-forward/pypy/module/cpyext/api.py pypy/branch/fast-forward/pypy/module/cpyext/datetime.py pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h pypy/branch/fast-forward/pypy/module/cpyext/patches/boost.patch pypy/branch/fast-forward/pypy/module/cpyext/pyobject.py pypy/branch/fast-forward/pypy/module/cpyext/sequence.py pypy/branch/fast-forward/pypy/module/cpyext/sliceobject.py pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py pypy/branch/fast-forward/pypy/module/cpyext/stubs.py pypy/branch/fast-forward/pypy/module/cpyext/test/foo.c pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_longobject.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_sliceobject.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py pypy/branch/fast-forward/pypy/module/imp/importing.py pypy/branch/fast-forward/pypy/module/imp/test/test_import.py pypy/branch/fast-forward/pypy/module/sys/__init__.py pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py pypy/branch/fast-forward/pypy/objspace/std/formatting.py pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py pypy/branch/fast-forward/pypy/rlib/rarithmetic.py pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py pypy/branch/fast-forward/pypy/rpython/rbuiltin.py pypy/branch/fast-forward/pypy/rpython/test/test_rbuiltin.py pypy/branch/fast-forward/pypy/tool/pytest/appsupport.py pypy/branch/fast-forward/pypy/tool/pytest/test/test_appsupport.py Log: merge from trunk Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Mon Jun 7 20:22:34 2010 @@ -569,11 +569,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -581,7 +584,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): Modified: pypy/branch/fast-forward/py/_code/source.py ============================================================================== --- pypy/branch/fast-forward/py/_code/source.py (original) +++ pypy/branch/fast-forward/py/_code/source.py Mon Jun 7 20:22:34 2010 @@ -17,8 +17,7 @@ """ a immutable object holding a source code fragment, possibly deindenting it. """ - _counter = 0 - + _compilecounter = 0 def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -197,12 +196,12 @@ if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno + base = "<%d-codegen " % self._compilecounter + self.__class__._compilecounter += 1 if not filename: - filename = '<%d-codegen %s:%d>' % (self._counter, fn, lineno) + filename = base + '%s:%d>' % (fn, lineno) else: - filename = '<%d-codegen %r %s:%d>' % (self._counter, filename, fn, lineno) - self.__class__._counter += 1 - + filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) @@ -230,7 +229,6 @@ py.std.inspect.modulesbyfile[filename] = None py.std.sys.modules[None] = m m.__loader__ = 1 - assert filename not in py.std.linecache.cache, filename py.std.linecache.cache[filename] = (1, None, lines, filename) return co Modified: pypy/branch/fast-forward/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/binaryop.py (original) +++ pypy/branch/fast-forward/pypy/annotation/binaryop.py Mon Jun 7 20:22:34 2010 @@ -442,7 +442,7 @@ return SomeUnicodeString() class __extend__(pairtype(SomeString, SomeUnicodeString), - pairtype(SomeString, SomeUnicodeString)): + pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") Modified: pypy/branch/fast-forward/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/builtin.py (original) +++ pypy/branch/fast-forward/pypy/annotation/builtin.py Mon Jun 7 20:22:34 2010 @@ -272,6 +272,12 @@ def OSError_init(s_self, *args): pass +def UnicodeDecodeError_init(s_self, *args): + pass + +def UnicodeEncodeError_init(s_self, *args): + pass + def WindowsError_init(s_self, *args): pass @@ -390,6 +396,8 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) +BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init +BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/fast-forward/pypy/annotation/classdef.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/classdef.py (original) +++ pypy/branch/fast-forward/pypy/annotation/classdef.py Mon Jun 7 20:22:34 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString + SomeString, SomeUnicodeString from pypy.annotation import description @@ -439,6 +439,16 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, + UnicodeDecodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeString(), + 'encoding': SomeString(), + 'reason': SomeString()}, + UnicodeEncodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeUnicodeString(), + 'encoding': SomeString(), + 'reason': SomeString()} } try: Modified: pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py Mon Jun 7 20:22:34 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_unicode_decode_error(self): + def f(): + try: + raise UnicodeDecodeError("x", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + return ude.end + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInteger) + def g(n): return [0,1,2,n] Modified: pypy/branch/fast-forward/pypy/doc/objspace.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/objspace.txt (original) +++ pypy/branch/fast-forward/pypy/doc/objspace.txt Mon Jun 7 20:22:34 2010 @@ -552,7 +552,7 @@ A number of options for configuration is here in `traceconfig.py`_. -.. _`found here` : getting-started.html#tracing-bytecode-and-operations-on-objects +.. _`found here` : getting-started-dev.html#tracing-bytecode-and-operations-on-objects .. _`Abstract Interpretation`: theory.html#abstract-interpretation .. _`traceconfig.py`: ../tool/traceconfig.py Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py Mon Jun 7 20:22:34 2010 @@ -1066,7 +1066,7 @@ return None def emitting_operation(self, op): - if op.has_no_side_effect(): + if op.opnum != rop.CALL_PURE and op.has_no_side_effect(): return if op.is_ovf(): return @@ -1079,6 +1079,7 @@ return if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or + opnum == rop.CALL_PURE or opnum == rop.CALL_ASSEMBLER): if opnum == rop.CALL_ASSEMBLER: effectinfo = None Modified: pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py Mon Jun 7 20:22:34 2010 @@ -1719,7 +1719,8 @@ self.history.record(rop.JUMP, exits, None) target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1729,7 +1730,8 @@ loop_tokens = sd.loop_tokens_exit_frame_with_exception_ref target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py Mon Jun 7 20:22:34 2010 @@ -2586,6 +2586,16 @@ ''' self.optimize_loop(ops, 'Not, Not', ops) + def test_call_pure_invalidates_caches(self): + ops = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call_pure(p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + self.optimize_loop(ops, 'Not, Not', ops) + def test_vref_nonvirtual_nonescape(self): ops = """ [p1] Modified: pypy/branch/fast-forward/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/fast-forward/pypy/module/_codecs/interp_codecs.py Mon Jun 7 20:22:34 2010 @@ -2,6 +2,7 @@ from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder +from pypy.rlib.objectmodel import we_are_translated class CodecState(object): def __init__(self, space): @@ -52,6 +53,9 @@ return replace, newpos return unicode_call_errorhandler + def _freeze_(self): + assert not self.codec_search_path + return False def register_codec(space, w_search_function): """register(search_function) @@ -75,6 +79,8 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ + assert not (space.config.translating and not we_are_translated()), \ + "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() w_result = state.codec_search_cache.get(normalized_encoding, None) @@ -215,11 +221,8 @@ else: encoding = space.str_w(w_encoding) w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) - if space.is_true(w_encoder): - w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) - return space.getitem(w_res, space.wrap(0)) - else: - assert 0, "XXX, what to do here?" + w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) + return space.getitem(w_res, space.wrap(0)) encode.unwrap_spec = [ObjSpace, W_Root, W_Root, str] def buffer_encode(space, s, errors='strict'): Modified: pypy/branch/fast-forward/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/api.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/api.py Mon Jun 7 20:22:34 2010 @@ -11,6 +11,7 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rlib.objectmodel import we_are_translated from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.gensupp import NameManager from pypy.tool.udir import udir from pypy.translator import platform from pypy.module.cpyext.state import State @@ -125,14 +126,18 @@ # the error value specifed in the API. # +cpyext_namespace = NameManager('cpyext_') + class ApiFunction: - def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED): + def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, + c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error + self.c_name = c_name # extract the signature from the (CPython-level) code object from pypy.interpreter import pycode @@ -159,6 +164,8 @@ wrapper = make_wrapper(space, self.callable) self._wrapper = wrapper wrapper.relax_sig_check = True + if self.c_name is not None: + wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): @@ -182,11 +189,16 @@ def decorate(func): func_name = func.func_name - api_function = ApiFunction(argtypes, restype, func, error) + if external: + c_name = None + else: + c_name = func_name + api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) func.api_func = api_function - assert func_name not in FUNCTIONS, "%s already registered" % func_name - assert func_name not in FUNCTIONS_STATIC + if external: + assert func_name not in FUNCTIONS, ( + "%s already registered" % func_name) if error is _NOT_SPECIFIED: raise ValueError("function %s has no return value for exceptions" @@ -261,8 +273,6 @@ unwrapper_raise = make_unwrapper(False) if external: FUNCTIONS[func_name] = api_function - else: - FUNCTIONS_STATIC[func_name] = api_function INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests return unwrapper_raise # used in 'normal' RPython code. return decorate @@ -277,7 +287,6 @@ INTERPLEVEL_API = {} FUNCTIONS = {} -FUNCTIONS_STATIC = {} SYMBOLS_C = [ 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse', 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords', @@ -439,6 +448,7 @@ # Make the wrapper for the cases (1) and (2) def make_wrapper(space, callable): + "NOT_RPYTHON" names = callable.api_func.argnames argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, [name.startswith("w_") for name in names]))) @@ -572,6 +582,7 @@ # back into Pypy space functions # Do not call this more than once per process def build_bridge(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -601,7 +612,10 @@ for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - global_objects.append('%s %s = NULL;' % (typ, name)) + if name.startswith('PyExc_'): + global_objects.append('%s %s;' % (typ[:-1], '_' + name)) + else: + global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -621,7 +635,6 @@ # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) - pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # populate static data for name, (typ, expr) in GLOBALS.iteritems(): @@ -632,6 +645,9 @@ isptr = False else: isptr = True + if name.startswith('PyExc_'): + isptr = False + INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') @@ -640,8 +656,14 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge,name) - py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + if name.startswith('PyPyExc_'): + # we already have the pointer + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) + else: + # we have a structure, get its address + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) w_type = space.type(w_obj) @@ -654,8 +676,12 @@ else: assert False, "Unknown static object: %s %s" % (typ, name) + pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') + # implement structure initialization code for name, func in FUNCTIONS.iteritems(): + if name.startswith('cpyext_'): # XXX hack + continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) @@ -666,6 +692,7 @@ return modulename.new(ext='') def generate_macros(export_symbols, rename=True, do_deref=True): + "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] for name in export_symbols: @@ -679,6 +706,8 @@ if not rename: newname = name pypy_macros.append('#define %s %s' % (name, newname)) + if name.startswith("PyExc_"): + pypy_macros.append('#define _%s _%s' % (name, newname)) renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols @@ -700,6 +729,7 @@ pypy_macros_h.write('\n'.join(pypy_macros)) def generate_decls_and_callbacks(db, export_symbols, api_struct=True): + "NOT_RPYTHON" # implement function callbacks and generate function decls functions = [] pypy_decls = [] @@ -734,6 +764,8 @@ if name.endswith('#'): name = name.replace("#", "") typ = typ.replace("*", "") + elif name.startswith('PyExc_'): + typ = 'PyObject*' pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) pypy_decls.append("#ifdef __cplusplus") @@ -746,6 +778,7 @@ return functions def build_eci(building_bridge, export_symbols, code): + "NOT_RPYTHON" # Build code and get pointer to the structure kwds = {} export_symbols_eci = export_symbols[:] @@ -768,6 +801,9 @@ for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): structs.append('%s %s;' % (typ[:-1], name[:-1])) + elif name.startswith('PyExc_'): + structs.append('extern PyTypeObject _%s;' % (name,)) + structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -793,6 +829,7 @@ def setup_library(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -812,6 +849,8 @@ # populate static data for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") + if name.startswith('PyExc_'): + name = '_' + name from pypy.module import cpyext w_obj = eval(expr) struct_ptr = make_ref(space, w_obj) @@ -822,8 +861,6 @@ for name, func in FUNCTIONS.iteritems(): deco = entrypoint("cpyext", func.argtypes, name, relax=True) deco(func.get_wrapper(space)) - for name, func in FUNCTIONS_STATIC.iteritems(): - func.get_wrapper(space).c_name = name setup_init_functions(eci) copy_header_files() Modified: pypy/branch/fast-forward/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/datetime.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/datetime.py Mon Jun 7 20:22:34 2010 @@ -1,16 +1,220 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pyobject import PyObject -from pypy.module.cpyext.api import cpython_api +from pypy.module.cpyext.api import ( + cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import +from pypy.interpreter.error import OperationError +from pypy.tool.sourcetools import func_renamer + +# API import function @cpython_api([], lltype.Void) -def PyDateTime_IMPORT(space): +def _PyDateTime_Import(space): return - at cpython_api([rffi.INT, rffi.INT, rffi.INT, rffi.INT], PyObject) +PyDateTime_Date = PyObject +PyDateTime_Time = PyObject +PyDateTime_DateTime = PyObject + +PyDeltaObjectStruct = lltype.ForwardReference() +cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct) +PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct) + +# Check functions + +def make_check_function(func_name, type_name): + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name) + def check(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return isinstance(obj, datatype) + """ % (type_name,))) + except OperationError: + return 0 + + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name + "Exact") + def check_exact(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return type(obj) is datatype + """ % (type_name,))) + except OperationError: + return 0 + +make_check_function("PyDateTime_Check", "datetime") +make_check_function("PyDate_Check", "date") +make_check_function("PyTime_Check", "time") +make_check_function("PyDelta_Check", "timedelta") + +# Constructors + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDate_FromDate(space, year, month, day): + """Return a datetime.date object with the specified year, month and day. + """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "date", + space.wrap(year), space.wrap(month), space.wrap(day)) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) def PyTime_FromTime(space, hour, minute, second, usecond): + """Return a ``datetime.time`` object with the specified hour, minute, second and + microsecond.""" + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "time", space.wrap(hour), space.wrap(minute), space.wrap(second), space.wrap(usecond)) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): + """Return a datetime.datetime object with the specified year, month, day, hour, + minute, second and microsecond. + """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "datetime", + space.wrap(year), space.wrap(month), space.wrap(day), + space.wrap(hour), space.wrap(minute), space.wrap(second), + space.wrap(usecond)) + raise NotImplementedError + + at cpython_api([PyObject], PyObject) +def PyDateTime_FromTimestamp(space, w_args): + """Create and return a new datetime.datetime object given an argument tuple + suitable for passing to datetime.datetime.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("datetime")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + + at cpython_api([PyObject], PyObject) +def PyDate_FromTimestamp(space, w_args): + """Create and return a new datetime.date object given an argument tuple + suitable for passing to datetime.date.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("date")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDelta_FromDSU(space, days, seconds, useconds): + """Return a datetime.timedelta object representing the given number of days, + seconds and microseconds. Normalization is performed so that the resulting + number of microseconds and seconds lie in the ranges documented for + datetime.timedelta objects. + """ + days = rffi.cast(lltype.Signed, days) + seconds = rffi.cast(lltype.Signed, seconds) + useconds = rffi.cast(lltype.Signed, useconds) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "timedelta", + space.wrap(days), space.wrap(seconds), space.wrap(useconds)) + +# Accessors + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_YEAR(space, w_obj): + """Return the year, as a positive int. + """ + return space.getattr(w_obj, space.wrap("year")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_MONTH(space, w_obj): + """Return the month, as an int from 1 through 12. + """ + return space.getattr(w_obj, space.wrap("month")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_DAY(space, w_obj): + """Return the day, as an int from 1 through 31. + """ + return space.getattr(w_obj, space.wrap("day")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) + +# XXX these functions are not present in the Python API +# But it does not seem possible to expose a different structure +# for types defined in a python module like lib/datetime.py. + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_DAYS(space, w_obj): + return space.getattr(w_obj, space.wrap("days")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_SECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("seconds")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("microseconds")) Modified: pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h Mon Jun 7 20:22:34 2010 @@ -27,6 +27,7 @@ # endif # define Py_LOCAL_INLINE(type) static __inline type __fastcall #endif +#define DL_IMPORT(RTYPE) PyAPI_FUNC(RTYPE) #include @@ -95,6 +96,7 @@ #include "pycobject.h" #include "bufferobject.h" #include "sliceobject.h" +#include "datetime.h" #include "pystate.h" // XXX This shouldn't be included here Modified: pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h Mon Jun 7 20:22:34 2010 @@ -0,0 +1,16 @@ +#ifndef DATETIME_H +#define DATETIME_H +#ifdef __cplusplus +extern "C" { +#endif + +#define PyDateTime_IMPORT _PyDateTime_Import() + +typedef struct { + PyObject_HEAD +} PyDateTime_Delta; + +#ifdef __cplusplus +} +#endif +#endif Modified: pypy/branch/fast-forward/pypy/module/cpyext/patches/boost.patch ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/patches/boost.patch (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/patches/boost.patch Mon Jun 7 20:22:34 2010 @@ -1,16 +1,3 @@ -Index: libs/python/src/object/class.cpp -=================================================================== ---- libs/python/src/object/class.cpp 2009-11-13 01:40:01 +0100 -+++ libs/python/src/object/class.cpp 2010-06-02 23:25:08 +0200 -@@ -195,7 +195,7 @@ - - namespace objects - { --#if PY_VERSION_HEX < 0x03000000 -+#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) - // XXX Not sure why this run into compiling error in Python 3 - extern "C" - { Index: libs/python/src/object/function.cpp =================================================================== --- libs/python/src/object/function.cpp 2010-04-04 07:19:57 +0200 @@ -50,14 +37,21 @@ =================================================================== --- tools/build/v2/user-config.jam 2008-07-15 15:53:41 +0200 +++ tools/build/v2/user-config.jam 2010-06-02 23:46:13 +0200 -@@ -84,3 +84,9 @@ +@@ -84,3 +84,16 @@ # Configure with an explicit installation prefix. # using qt : /usr/opt/qt ; + ++# ------------------- ++# PyPy configuration. ++# ------------------- ++ ++PYPY_HOME = /home/amaury/trunk ; ++ +using python : 2.5 -+ : /home/amaury/trunk/pypy/pypy-c -+ : /home/amaury/trunk/pypy/module/cpyext/include -+ /home/amaury/trunk/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/pypy-c # interpreter ++ : $(PYPY_HOME)/pypy/module/cpyext/include # include paths ++ $(PYPY_HOME)/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/_interfaces # library path + ; Modified: pypy/branch/fast-forward/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/pyobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/pyobject.py Mon Jun 7 20:22:34 2010 @@ -2,9 +2,9 @@ from pypy.interpreter.baseobjspace import W_Root, SpaceCache from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, bootstrap_function, \ - PyObject, PyObjectP, ADDR, CANNOT_FAIL, \ - Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr +from pypy.module.cpyext.api import ( + cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR, + CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) from pypy.module.cpyext.state import State from pypy.objspace.std.typeobject import W_TypeObject from pypy.rlib.objectmodel import specialize, we_are_translated @@ -263,9 +263,9 @@ Allocates a PyObject, and fills its fields with info from the given intepreter object. """ + state = space.fromcache(RefcountState) w_type = space.type(w_obj) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) py_obj = state.get_from_lifeline(w_obj) if py_obj: Py_IncRef(space, py_obj) @@ -274,7 +274,6 @@ typedescr = get_typedescr(w_obj.typedef) py_obj = typedescr.allocate(space, w_type, itemcount=itemcount) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) state.set_lifeline(w_obj, py_obj) typedescr.attach(space, py_obj, w_obj) return py_obj @@ -333,7 +332,7 @@ # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) - if ref_type == ref: + if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) Modified: pypy/branch/fast-forward/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/sequence.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/sequence.py Mon Jun 7 20:22:34 2010 @@ -6,6 +6,14 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.objspace.std import listobject, tupleobject + at cpython_api([PyObject, Py_ssize_t], PyObject) +def PySequence_Repeat(space, w_obj, count): + """Return the result of repeating sequence object o count times, or NULL on + failure. This is the equivalent of the Python expression o * count. + + This function used an int type for count. This might require + changes in your code for properly supporting 64-bit systems.""" + return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PySequence_Check(space, w_obj): @@ -91,6 +99,12 @@ return space.getitem(w_obj, space.wrap(i)) @cpython_api([PyObject], PyObject) +def PySequence_List(space, w_obj): + """Return a list object with the same contents as the arbitrary sequence o. The + returned list is guaranteed to be new.""" + return space.call_function(space.w_list, w_obj) + + at cpython_api([PyObject], PyObject) def PySequence_Tuple(space, w_obj): """Return a tuple object with the same contents as the arbitrary sequence o or NULL on failure. If o is a tuple, a new reference will be returned, Modified: pypy/branch/fast-forward/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/sliceobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/sliceobject.py Mon Jun 7 20:22:34 2010 @@ -56,6 +56,12 @@ the same names. Any of the values may be NULL, in which case the None will be used for the corresponding attribute. Return NULL if the new object could not be allocated.""" + if w_start is None: + w_start = space.w_None + if w_stop is None: + w_stop = space.w_None + if w_step is None: + w_step = space.w_None return W_SliceObject(w_start, w_stop, w_step) @cpython_api([PySliceObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, Modified: pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py Mon Jun 7 20:22:34 2010 @@ -5,15 +5,17 @@ from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc, - ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc) + ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc, + descrgetfunc, descrsetfunc) from pypy.module.cpyext.pyobject import from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.argument import Arguments from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name - +from pypy.rlib.objectmodel import specialize +from pypy.tool.sourcetools import func_renamer +from pypy.rpython.annlowlevel import llhelper # XXX: Also defined in object.h Py_LT = 0 @@ -39,7 +41,7 @@ func_init = rffi.cast(initproc, func) res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) if rffi.cast(lltype.Signed, res) == -1: - space.fromcache(State).check_and_raise_exception() + space.fromcache(State).check_and_raise_exception(always=True) return None def wrap_unaryfunc(space, w_self, w_args, func): @@ -81,6 +83,44 @@ if rffi.cast(lltype.Signed, res) == -1: space.fromcache(State).check_and_raise_exception(always=True) +def wrap_descr_get(space, w_self, w_args, func): + func_target = rffi.cast(descrgetfunc, func) + args_w = space.fixedview(w_args) + if len(args_w) == 1: + w_obj, = args_w + w_type = None + elif len(args_w) == 2: + w_obj, w_type = args_w + else: + raise operationerrfmt( + space.w_TypeError, + "expected 1 or 2 arguments, got %d", len(args_w)) + if w_obj is space.w_None: + w_obj = None + if w_type is space.w_None: + w_type = None + if w_obj is None and w_type is None: + raise OperationError( + space.w_TypeError, + space.wrap("__get__(None, None) is invalid")) + return generic_cpy_call(space, func_target, w_self, w_obj, w_type) + +def wrap_descr_set(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 2) + w_obj, w_value = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, w_value) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_descr_delete(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 1) + w_obj, = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, None) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + def wrap_call(space, w_self, w_args, func, w_kwds): func_target = rffi.cast(ternaryfunc, func) return generic_cpy_call(space, func_target, w_self, w_args, w_kwds) @@ -174,22 +214,64 @@ return space.call(w_self, w_args, w_kwds) @cpython_api([PyObject], PyObject, external=False) +def slot_tp_str(space, w_self): + return space.str(w_self) + + at cpython_api([PyObject], PyObject, external=False) def slot_nb_int(space, w_self): return space.int(w_self) - at cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1, external=False) -def slot_tp_setattro(space, w_self, w_name, w_value): - # XXX this is probably wrong when a subtype's tp_setattro - # delegates to PyType_Type.tp_setattro! - if w_value is not None: - space.setattr(w_self, w_name, w_value) +from pypy.rlib.nonconst import NonConstant + +SLOTS = {} + + at specialize.memo() +def get_slot_tp_function(space, typedef, name): + key = (typedef, name) + try: + return SLOTS[key] + except KeyError: + ret = build_slot_tp_function(space, typedef, name) + SLOTS[key] = ret + return ret + +def build_slot_tp_function(space, typedef, name): + w_type = space.gettypeobject(typedef) + + if name == 'tp_setattro': + setattr_fn = w_type.getdictvalue(space, '__setattr__') + delattr_fn = w_type.getdictvalue(space, '__delattr__') + if setattr_fn is None: + return + + @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, + error=-1, external=True) # XXX should not be exported + @func_renamer("cpyext_tp_setattro_%s" % (typedef.name,)) + def slot_tp_setattro(space, w_self, w_name, w_value): + if w_value is not None: + space.call_function(setattr_fn, w_self, w_name, w_value) + else: + space.call_function(delattr_fn, w_self, w_name) + return 0 + api_func = slot_tp_setattro.api_func else: - space.delattr(w_self, w_name) - return 0 + return + + return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) PyWrapperFlag_KEYWORDS = 1 -# adopted from typeobject.c +class TypeSlot: + def __init__(self, method_name, slot_name, function, wrapper1, wrapper2, doc): + self.method_name = method_name + self.slot_name = slot_name + self.slot_names = ("c_" + slot_name).split(".") + self.slot_func = function + self.wrapper_func = wrapper1 + self.wrapper_func_kwds = wrapper2 + self.doc = doc + +# adapted from typeobject.c def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS): if WRAPPER is None: wrapper = None @@ -201,23 +283,22 @@ wrapper = wrap_getattr function = globals().get(FUNCTION, None) - slotname = ("c_" + SLOT).split(".") assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func, w_kwds): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = None wrapper2 = wrapper else: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = wrapper wrapper2 = None - return (NAME, slotname, function, wrapper1, wrapper2, DOC) + return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC): return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0) @@ -470,7 +551,12 @@ for regex, repl in slotdef_replacements: slotdefs_str = re.sub(regex, repl, slotdefs_str) -slotdefs = unrolling_iterable(eval(slotdefs_str)) +slotdefs_for_tp_slots = unrolling_iterable( + [(x.method_name, x.slot_name, x.slot_names, x.slot_func) + for x in eval(slotdefs_str)]) +slotdefs_for_wrappers = unrolling_iterable( + [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) + for x in eval(slotdefs_str)]) if __name__ == "__main__": print slotdefs_str Modified: pypy/branch/fast-forward/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/stubs.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/stubs.py Mon Jun 7 20:22:34 2010 @@ -23,7 +23,7 @@ _inittab = lltype.Void PyThreadState = lltype.Void PyInterpreterState = lltype.Void -PyOS_sighandler_t = lltype.Void +#PyOS_sighandler_t = lltype.Void Py_UNICODE = lltype.Void PyCompilerFlags = lltype.Void _node = lltype.Void @@ -574,62 +574,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_Check(space, ob): - """Return true if ob is of type PyDateTime_DateType or a subtype of - PyDateTime_DateType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_Check(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType or a subtype of - PyDateTime_DateTimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType. ob must not - be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_Check(space, ob): - """Return true if ob is of type PyDateTime_TimeType or a subtype of - PyDateTime_TimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_TimeType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_Check(space, ob): - """Return true if ob is of type PyDateTime_DeltaType or a subtype of - PyDateTime_DeltaType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DeltaType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyTZInfo_Check(space, ob): """Return true if ob is of type PyDateTime_TZInfoType or a subtype of PyDateTime_TZInfoType. ob must not be NULL. @@ -643,108 +587,6 @@ """ raise NotImplementedError - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): - """Return a datetime.date object with the specified year, month and day. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): - """Return a datetime.datetime object with the specified year, month, day, hour, - minute, second and microsecond. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): - """Return a datetime.timedelta object representing the given number of days, - seconds and microseconds. Normalization is performed so that the resulting - number of microseconds and seconds lie in the ranges documented for - datetime.timedelta objects. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_YEAR(space, o): - """Return the year, as a positive int. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_MONTH(space, o): - """Return the month, as an int from 1 through 12. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_DAY(space, o): - """Return the day, as an int from 1 through 31. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDateTime_FromTimestamp(space, args): - """Create and return a new datetime.datetime object given an argument tuple - suitable for passing to datetime.datetime.fromtimestamp(). - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDate_FromTimestamp(space, args): - """Create and return a new datetime.date object given an argument tuple - suitable for passing to datetime.date.fromtimestamp(). - """ - raise NotImplementedError - @cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject) def PyDescr_NewGetSet(space, type, getset): raise NotImplementedError @@ -2363,9 +2205,7 @@ @cpython_api([PyObject], PyObject) def PyObject_Dir(space, o): - """This is equivalent to the Python expression dir(o), returning a (possibly - empty) list of strings appropriate for the object argument, or NULL if there - was an error. If the argument is NULL, this is like the Python dir(), + """This is equivalent to the Python expression dir(o), returning a (possibly empty) list of strings appropriate for the object argument, or NULL if there was an error. If the argument is NULL, this is like the Python dir(), returning the names of the current locals; in this case, if no execution frame is active then NULL is returned but PyErr_Occurred() will return false.""" raise NotImplementedError @@ -2403,15 +2243,6 @@ func.""" raise NotImplementedError - at cpython_api([PyObject, Py_ssize_t], PyObject) -def PySequence_Repeat(space, o, count): - """Return the result of repeating sequence object o count times, or NULL on - failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject], PyObject) def PySequence_InPlaceConcat(space, o1, o2): """Return the concatenation of o1 and o2 on success, and NULL on failure. @@ -2474,12 +2305,6 @@ in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PySequence_List(space, o): - """Return a list object with the same contents as the arbitrary sequence o. The - returned list is guaranteed to be new.""" - raise NotImplementedError - @cpython_api([PyObject], PyObjectP, error=lltype.nullptr(PyObjectP.TO)) def PySequence_Fast_ITEMS(space, o): """Return the underlying array of PyObject pointers. Assumes that o was returned Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/foo.c ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/foo.c (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/foo.c Mon Jun 7 20:22:34 2010 @@ -483,6 +483,90 @@ 0 /*tp_weaklist*/ }; +PyObject * prop_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + if (obj == NULL) + obj = Py_None; + if (type == NULL) + type = Py_None; + + return PyTuple_Pack(3, self, obj, type); +} + +int prop_descr_set(PyObject *self, PyObject *obj, PyObject *value) +{ + int res; + if (value != NULL) { + PyObject *result = PyTuple_Pack(2, self, value); + res = PyObject_SetAttrString(obj, "y", result); + Py_DECREF(result); + } + else { + res = PyObject_SetAttrString(obj, "z", self); + } + return res; +} + + +PyTypeObject SimplePropertyType = { + PyObject_HEAD_INIT(NULL) + 0, + "foo.Property", + sizeof(PyObject), + 0, + 0, /*tp_dealloc*/ + 0, /*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*/ + + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + 0, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + prop_descr_get, /*tp_descr_get*/ + prop_descr_set, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + 0, /*tp_init*/ + 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ + 0, /*tp_new*/ + 0, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + /* Initialize this module. */ @@ -506,6 +590,8 @@ return; if (PyType_Ready(&InitErrType) < 0) return; + if (PyType_Ready(&SimplePropertyType) < 0) + return; m = Py_InitModule("foo", foo_functions); if (m == NULL) return; @@ -522,4 +608,6 @@ return; if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0) return; + if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0) + return; } Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py Mon Jun 7 20:22:34 2010 @@ -1,7 +1,81 @@ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.test.test_api import BaseApiTest +import datetime class TestDatetime(BaseApiTest): + def test_date(self, space, api): + w_date = api.PyDate_FromDate(2010, 06, 03) + assert space.unwrap(space.str(w_date)) == '2010-06-03' + + assert api.PyDate_Check(w_date) + assert api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date)])) == ( + 2010, 06, 03) + def test_time(self, space, api): w_time = api.PyTime_FromTime(23, 15, 40, 123456) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' + + assert api.PyTime_Check(w_time) + assert api.PyTime_CheckExact(w_time) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_TIME_GET_HOUR(w_time), + api.PyDateTime_TIME_GET_MINUTE(w_time), + api.PyDateTime_TIME_GET_SECOND(w_time), + api.PyDateTime_TIME_GET_MICROSECOND(w_time)])) == ( + 23, 15, 40, 123456) + + def test_datetime(self, space, api): + w_date = api.PyDateTime_FromDateAndTime( + 2010, 06, 03, 23, 15, 40, 123456) + assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456' + + assert api.PyDateTime_Check(w_date) + assert api.PyDateTime_CheckExact(w_date) + assert api.PyDate_Check(w_date) + assert not api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date), + api.PyDateTime_DATE_GET_HOUR(w_date), + api.PyDateTime_DATE_GET_MINUTE(w_date), + api.PyDateTime_DATE_GET_SECOND(w_date), + api.PyDateTime_DATE_GET_MICROSECOND(w_date)])) == ( + 2010, 06, 03, 23, 15, 40, 123456) + + def test_delta(self, space, api): + w_delta = space.appexec( + [space.wrap(3), space.wrap(15)], """(days, seconds): + from datetime import timedelta + return timedelta(days, seconds) + """) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + w_delta = api.PyDelta_FromDSU(10, 20, 30) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_DELTA_GET_DAYS(w_delta), + api.PyDateTime_DELTA_GET_SECONDS(w_delta), + api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta)])) == ( + 10, 20, 30) + + def test_fromtimestamp(self, space, api): + w_args = space.wrap((0,)) + w_date = api.PyDate_FromTimestamp(w_args) + date = datetime.date.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) + + w_args = space.wrap((0,)) + w_date = api.PyDateTime_FromTimestamp(w_args) + date = datetime.datetime.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_longobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_longobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_longobject.py Mon Jun 7 20:22:34 2010 @@ -76,7 +76,8 @@ """ return PyLong_FromUnsignedLong((unsigned long)-1); """)]) - assert module.from_unsignedlong() == (1<<32) - 1 + import sys + assert module.from_unsignedlong() == 2 * sys.maxint + 1 def test_fromlonglong(self): module = self.import_extension('foo', [ Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py Mon Jun 7 20:22:34 2010 @@ -8,7 +8,7 @@ def test_sequence(self, space, api): w_t = space.wrap((1, 2, 3, 4)) assert api.PySequence_Fast(w_t, "message") is w_t - w_l = space.wrap((1, 2, 3, 4)) + w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l assert space.int_w(api.PySequence_Fast_GET_ITEM(w_l, 1)) == 2 @@ -23,6 +23,19 @@ assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + w_seq = api.PySequence_List(w_set) + assert space.type(w_seq) is space.w_list + assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + + def test_repeat(self, space, api): + def test(seq, count): + w_seq = space.wrap(seq) + w_repeated = api.PySequence_Repeat(w_seq, count) + assert space.eq_w(w_repeated, space.wrap(seq * count)) + + test((1, 2, 3, 4), 3) + test([1, 2, 3, 4], 3) + def test_concat(self, space, api): w_t1 = space.wrap(range(4)) w_t2 = space.wrap(range(4, 8)) Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_sliceobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_sliceobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_sliceobject.py Mon Jun 7 20:22:34 2010 @@ -43,3 +43,12 @@ ]) s = slice(10, 20, 30) assert module.clone(s) == s + + def test_nulls(self): + module = self.import_extension('foo', [ + ("nullslice", "METH_NOARGS", + """ + return PySlice_New(NULL, NULL, NULL); + """), + ]) + assert module.nullslice() == slice(None, None, None) Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py Mon Jun 7 20:22:34 2010 @@ -192,6 +192,41 @@ assert d[cmpr] == 72 assert d[3] == 72 + def test_descriptor(self): + module = self.import_module("foo") + prop = module.Property() + class C(object): + x = prop + obj = C() + assert obj.x == (prop, obj, C) + assert C.x == (prop, None, C) + + obj.x = 2 + assert obj.y == (prop, 2) + del obj.x + assert obj.z == prop + + def test_tp_dict(self): + foo = self.import_module("foo") + module = self.import_extension('test', [ + ("read_tp_dict", "METH_O", + ''' + PyObject *method; + if (!args->ob_type->tp_dict) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + method = PyDict_GetItemString( + args->ob_type->tp_dict, "copy"); + Py_INCREF(method); + return method; + ''' + ) + ]) + obj = foo.new() + assert module.read_tp_dict(obj) == foo.fooType.copy + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): @@ -240,11 +275,17 @@ PyErr_SetString(PyExc_ValueError, "missing tp_setattro"); return NULL; } + if (args->ob_type->tp_setattro == + args->ob_type->tp_base->tp_setattro) + { + PyErr_SetString(PyExc_ValueError, "recursive tp_setattro"); + return NULL; + } Py_RETURN_TRUE; ''' ) ]) - assert module.test_type(None) + assert module.test_type(type(None)) def test_nb_int(self): module = self.import_extension('foo', [ @@ -283,3 +324,21 @@ def __call__(self, *args): return args assert module.tp_call(C(), ('x', 2)) == ('x', 2) + + def test_tp_str(self): + module = self.import_extension('foo', [ + ("tp_str", "METH_O", + ''' + if (!args->ob_type->tp_str) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + return args->ob_type->tp_str(args); + ''' + ) + ]) + class C: + def __str__(self): + return "text" + assert module.tp_str(C()) == "text" Modified: pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py Mon Jun 7 20:22:34 2010 @@ -25,7 +25,8 @@ from pypy.module.cpyext.typeobjectdefs import ( PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, PyNumberMethods) -from pypy.module.cpyext.slotdefs import slotdefs +from pypy.module.cpyext.slotdefs import ( + slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function) from pypy.interpreter.error import OperationError from pypy.rlib.rstring import rsplit from pypy.rlib.objectmodel import specialize @@ -102,48 +103,60 @@ def update_all_slots(space, w_type, pto): # XXX fill slots in pto - for method_name, slot_name, slot_func, _, _, _ in slotdefs: + + typedef = w_type.instancetypedef + for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: w_descr = w_type.lookup(method_name) if w_descr is None: # XXX special case iternext continue - if slot_func is None: + + slot_func_helper = None + + if slot_func is None and typedef is not None: + get_slot = get_slot_tp_function(space, typedef, slot_name) + if get_slot: + slot_func_helper = get_slot() + elif slot_func: + slot_func_helper = llhelper(slot_func.api_func.functype, + slot_func.api_func.get_wrapper(space)) + + if slot_func_helper is None: if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: os.write(2, method_name + " defined by the type but no slot function defined!\n") continue - slot_func_helper = llhelper(slot_func.api_func.functype, - slot_func.api_func.get_wrapper(space)) + # XXX special case wrapper-functions and use a "specific" slot func - if len(slot_name) == 1: - setattr(pto, slot_name[0], slot_func_helper) + if len(slot_names) == 1: + setattr(pto, slot_names[0], slot_func_helper) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: - if slot_name[0] == 'c_tp_as_number': + if slot_names[0] == 'c_tp_as_number': STRUCT_TYPE = PyNumberMethods else: raise AssertionError( - "Structure not allocated: %s" % (slot_name[0],)) + "Structure not allocated: %s" % (slot_names[0],)) struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) - setattr(pto, slot_name[0], struct) + setattr(pto, slot_names[0], struct) - setattr(struct, slot_name[1], slot_func_helper) + setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): # XXX support PyObject_HashNotImplemented - for method_name, slot_name, _, wrapper_func, wrapper_func_kwds, doc in slotdefs: + for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue - if len(slot_name) == 1: - func = getattr(pto, slot_name[0]) + if len(slot_names) == 1: + func = getattr(pto, slot_names[0]) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: continue - func = getattr(struct, slot_name[1]) + func = getattr(struct, slot_names[1]) func_voidp = rffi.cast(rffi.VOIDP_real, func) if not func: continue @@ -363,12 +376,13 @@ @cpython_api([PyObject], lltype.Void, external=False) def type_dealloc(space, obj): + from pypy.module.cpyext.object import PyObject_dealloc obj_pto = rffi.cast(PyTypeObjectPtr, obj) - type_pto = obj.c_ob_type base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base) Py_DecRef(space, obj_pto.c_tp_bases) Py_DecRef(space, obj_pto.c_tp_mro) Py_DecRef(space, obj_pto.c_tp_cache) # let's do it like cpython + Py_DecRef(space, obj_pto.c_tp_dict) if obj_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: if obj_pto.c_tp_as_buffer: lltype.free(obj_pto.c_tp_as_buffer, flavor='raw') @@ -376,11 +390,7 @@ lltype.free(obj_pto.c_tp_as_number, flavor='raw') Py_DecRef(space, base_pyo) rffi.free_charp(obj_pto.c_tp_name) - obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto) - generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp) - if type_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: - pto = rffi.cast(PyObject, type_pto) - Py_DecRef(space, pto) + PyObject_dealloc(space, obj) def type_attach(space, py_obj, w_type): @@ -494,6 +504,8 @@ # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free + if not pto.c_tp_setattro: + pto.c_tp_setattro = base.c_tp_setattro finally: Py_DecRef(space, base_pyo) @@ -532,8 +544,6 @@ """ Sets up tp_bases, necessary before creating the interpreter type. """ - pto.c_tp_dict = lltype.nullptr(PyObject.TO) # not supported - base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: @@ -558,6 +568,16 @@ for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): inherit_slots(space, pto, w_base) + if not pto.c_tp_setattro: + from pypy.module.cpyext.object import PyObject_GenericSetAttr + pto.c_tp_setattro = llhelper( + PyObject_GenericSetAttr.api_func.functype, + PyObject_GenericSetAttr.api_func.get_wrapper(space)) + + if w_obj.is_cpytype(): + Py_DecRef(space, pto.c_tp_dict) + pto.c_tp_dict = make_ref(space, w_obj.getdict()) + @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. Modified: pypy/branch/fast-forward/pypy/module/imp/importing.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/imp/importing.py (original) +++ pypy/branch/fast-forward/pypy/module/imp/importing.py Mon Jun 7 20:22:34 2010 @@ -145,7 +145,7 @@ msg = "Attempted relative import in non-package" raise OperationError(space.w_ValueError, w(msg)) w_mod = absolute_import_try(space, modulename, 0, fromlist_w) - if w_mod is None and not space.is_w(w_mod, space.w_None): + if w_mod is None or space.is_w(w_mod, space.w_None): w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0) if rel_modulename is not None: space.setitem(space.sys.get('modules'), w(rel_modulename), space.w_None) @@ -178,13 +178,11 @@ else: level = 0 first = None - while last_dot != -1: - assert last_dot >= 0 # bah + while last_dot >= 0: last_dot = modulename.find('.', last_dot + 1) - if last_dot == -1: + if last_dot < 0: w_mod = check_sys_modules_w(space, modulename) else: - assert last_dot >= 0 w_mod = check_sys_modules_w(space, modulename[:last_dot]) if w_mod is None or space.is_w(w_mod, space.w_None): return None Modified: pypy/branch/fast-forward/pypy/module/imp/test/test_import.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/imp/test/test_import.py (original) +++ pypy/branch/fast-forward/pypy/module/imp/test/test_import.py Mon Jun 7 20:22:34 2010 @@ -457,6 +457,16 @@ def test_reload_infinite(self): import infinite_reload + def test_explicitly_missing(self): + import sys + sys.modules['foobarbazmod'] = None + try: + import foobarbazmod + assert False, "should have failed, got instead %r" % ( + foobarbazmod,) + except ImportError: + pass + def _getlong(data): x = marshal.dumps(data) return x[-4:] Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Mon Jun 7 20:22:34 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.interpreter.error import OperationError +from pypy.rlib.objectmodel import we_are_translated import sys class Module(MixedModule): @@ -95,8 +96,12 @@ self.space.setitem(w_modules, w_name, w_module) def startup(self, space): - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) + if space.config.translating and not we_are_translated(): + # don't get the filesystemencoding at translation time + assert self.filesystemencoding is None + else: + from pypy.module.sys.interp_encoding import _getfilesystemencoding + self.filesystemencoding = _getfilesystemencoding(space) def getmodule(self, name): space = self.space Modified: pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py Mon Jun 7 20:22:34 2010 @@ -1,5 +1,6 @@ import sys from pypy.rlib import rlocale +from pypy.rlib.objectmodel import we_are_translated def getdefaultencoding(space): """Return the current default string encoding used by the Unicode @@ -18,6 +19,8 @@ space.sys.defaultencoding = encoding def get_w_default_encoder(space): + assert not (space.config.translating and not we_are_translated()), \ + "get_w_default_encoder() should not be called during translation" w_encoding = space.wrap(space.sys.defaultencoding) mod = space.getbuiltinmodule("_codecs") w_lookup = space.getattr(mod, space.wrap("lookup")) @@ -40,6 +43,8 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: + if loc_codeset == 'ANSI_X3.4-1968': + loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), Modified: pypy/branch/fast-forward/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/formatting.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/formatting.py Mon Jun 7 20:22:34 2010 @@ -474,12 +474,6 @@ [_name[-1] for _name in dir(StringFormatter) if len(_name) == 5 and _name.startswith('fmt_')]) -def is_list_of_chars_or_unichars(ann, bk): - from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint - if not isinstance(ann.listdef.listitem.s_value, - (SomeChar, SomeUnicodeCodePoint)): - raise TypeError("Formatter should return as a result a list of chars or unichars, otherwise we miss important optimization") - def format(space, w_fmt, values_w, w_valuedict=None, do_unicode=False): "Entry point" if not do_unicode: Modified: pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py Mon Jun 7 20:22:34 2010 @@ -3,6 +3,8 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii,\ + unicode_encode_utf_8, unicode_encode_ascii from sys import maxint @@ -185,13 +187,27 @@ return encoding, errors def encode_object(space, w_object, encoding, errors): - # XXX write down shortcuts for performance for common encodings, - # just like CPython if encoding is None: # Get the encoder functions as a wrapped object. # This lookup is cached. w_encoder = space.sys.get_w_default_encoder() else: + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_ascii(u, len(u), None)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_utf_8(u, len(u), None)) + except UnicodeEncodeError, uee: + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([ + space.wrap(uee.encoding), + space.wrap(uee.object), + space.wrap(uee.start), + space.wrap(uee.end), + space.wrap(uee.reason)])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -207,9 +223,23 @@ return w_retval def decode_object(space, w_obj, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") if encoding is None: encoding = getdefaultencoding(space) + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_ascii(s, len(s), None)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_utf_8(s, len(s), None)[0]) + except UnicodeDecodeError, ude: + raise OperationError(space.w_UnicodeDecodeError, space.newtuple( + [space.wrap(ude.encoding), space.wrap(ude.object), + space.wrap(ude.start), space.wrap(ude.end), + space.wrap(ude.reason)])) + w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: w_retval = space.call_function(w_decode, w_obj, space.wrap(encoding)) Modified: pypy/branch/fast-forward/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rarithmetic.py Mon Jun 7 20:22:34 2010 @@ -178,12 +178,6 @@ else: return super(base_int, klass).__new__(klass, val) - def __int__(self): - if self < LONG_TEST: - return long.__int__(self) - else: - return intmask(self) - def __add__(self, other): x = long(self) y = long(other) Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py Mon Jun 7 20:22:34 2010 @@ -114,7 +114,10 @@ #self.binary_test(lambda x, y: pow(x, y, 42), (2, 3, 5, 1000)) def test_back_to_int(self): - assert int(r_uint(-1)) == -1 + #assert int(r_uint(-1)) == -1 + # ^^^ that looks wrong IMHO: int(x) should not by itself return + # an integer that has a different value than x, especially + # if x is a subclass of long. assert int(r_uint(1)) == 1 def unary_test(self, f): Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py Mon Jun 7 20:22:34 2010 @@ -18,6 +18,7 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -296,7 +297,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError + raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' Modified: pypy/branch/fast-forward/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/fast-forward/pypy/rpython/rbuiltin.py Mon Jun 7 20:22:34 2010 @@ -270,6 +270,37 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) +def rtype_UnicodeDecodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeDecodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + TPS = [hop.args_r[0], r_str, r_str, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + +def rtype_UnicodeEncodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeEncodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + r_unicode = hop.rtyper.type_system.rstr.unicode_repr + TPS = [hop.args_r[0], r_str, r_unicode, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + def rtype_WindowsError__init__(hop): if hop.nb_args == 2: raise TyperError("WindowsError() should not be called with " @@ -329,6 +360,8 @@ BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( rtype_OSError__init__) +BUILTIN_TYPER[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = rtype_UnicodeDecodeError_init +BUILTIN_TYPER[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = rtype_UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rbuiltin.py Mon Jun 7 20:22:34 2010 @@ -496,6 +496,35 @@ res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy()) assert res == 123 + def test_unicode_errors(self): + def f(): + try: + raise UnicodeDecodeError("xx", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == "x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + + def f(): + try: + raise UnicodeEncodeError("xx", u"x", 0, 1, "reason") + except UnicodeEncodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == u"x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): Modified: pypy/branch/fast-forward/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/appsupport.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/appsupport.py Mon Jun 7 20:22:34 2010 @@ -86,11 +86,18 @@ if debug_excs: self._excinfo = debug_excs[0] + def __repr__(self): + return "" % self.operr.errorstr(self.space) + def exconly(self, tryshort=True): return '(application-level) ' + self.operr.errorstr(self.space) def errisinstance(self, exc): clsname = exc.__name__ + # we can only check for builtin exceptions + # as there is no canonical applevel one for custom interplevel ones + if exc.__module__ != "exceptions": + return False try: w_exc = getattr(self.space, 'w_' + clsname) except KeyboardInterrupt: Modified: pypy/branch/fast-forward/pypy/tool/pytest/test/test_appsupport.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/test/test_appsupport.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/test/test_appsupport.py Mon Jun 7 20:22:34 2010 @@ -113,6 +113,19 @@ "*E*application-level*NameError*x*not defined", ]) +def test_applevel_raise_keyerror(testdir): + setpypyconftest(testdir) + p = testdir.makepyfile(""" + def app_test_raises(): + raise KeyError(42) + pass + """) + result = testdir.runpytest(p, "-s") + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "*E*application-level*KeyError*42*", + ]) + def app_test_raises(): info = raises(TypeError, id) assert info.type is TypeError From benjamin at codespeak.net Mon Jun 7 21:10:20 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 7 Jun 2010 21:10:20 +0200 (CEST) Subject: [pypy-svn] r75183 - pypy/trunk/pypy/rlib/test Message-ID: <20100607191020.DC358282BDB@codespeak.net> Author: benjamin Date: Mon Jun 7 21:09:35 2010 New Revision: 75183 Modified: pypy/trunk/pypy/rlib/test/test_rlocale.py Log: be robust for those of us who are't polish Modified: pypy/trunk/pypy/rlib/test/test_rlocale.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rlocale.py (original) +++ pypy/trunk/pypy/rlib/test/test_rlocale.py Mon Jun 7 21:09:35 2010 @@ -14,7 +14,8 @@ py.test.skip("polish locale unsupported") def teardown_class(cls): - setlocale(LC_ALL, cls.oldlocale) + if hasattr(cls, "oldlocale"): + setlocale(LC_ALL, cls.oldlocale) def test_setlocale_worked(self): assert u"?".isupper() From getxsick at codespeak.net Mon Jun 7 22:24:02 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 7 Jun 2010 22:24:02 +0200 (CEST) Subject: [pypy-svn] r75184 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100607202402.25DA5282BDB@codespeak.net> Author: getxsick Date: Mon Jun 7 22:24:00 2010 New Revision: 75184 Added: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py - copied unchanged from r75133, pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py - copied, changed from r75133, pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Removed: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py Log: rename rlib/jitffi.py to rlib/rjitffi.py Copied: pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py (from r75133, pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py) ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py Mon Jun 7 22:24:00 2010 @@ -1,4 +1,4 @@ -from pypy.rlib import jitffi +from pypy.rlib import rjitffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform from pypy.rpython.lltypesystem import rffi, lltype @@ -57,10 +57,10 @@ cls.lib_name = cls.preprare_c_example() def test_missing_lib(self): - py.test.raises(OSError, jitffi.CDLL, 'xxxfoo888baryyy') + py.test.raises(OSError, rjitffi.CDLL, 'xxxfoo888baryyy') def test_get(self): - lib = jitffi.CDLL(self.lib_name) + lib = rjitffi.CDLL(self.lib_name) func = lib.get('add_integers', ['int', 'int'], 'int') assert 3 == func.call(1,2) @@ -76,7 +76,7 @@ assert 2.7 == func.call(1.2, 1.5) def test_get_void(self): - lib = jitffi.CDLL(self.lib_name) + lib = rjitffi.CDLL(self.lib_name) func = lib.get('fvoid', [], 'int') assert 1 == func.call() @@ -87,7 +87,7 @@ assert func.call(1, 2) is None def test_undefined_func(self): - lib = jitffi.CDLL(self.lib_name) + lib = rjitffi.CDLL(self.lib_name) # xxxfoo888baryyy - not existed function py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', []) py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') From benjamin at codespeak.net Mon Jun 7 22:25:05 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 7 Jun 2010 22:25:05 +0200 (CEST) Subject: [pypy-svn] r75185 - in pypy/branch/fast-forward/pypy/rlib: . test Message-ID: <20100607202505.72E1A282BDB@codespeak.net> Author: benjamin Date: Mon Jun 7 22:25:03 2010 New Revision: 75185 Modified: pypy/branch/fast-forward/pypy/rlib/rlocale.py pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py Log: function for getting numeric formatting locale data Modified: pypy/branch/fast-forward/pypy/rlib/rlocale.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rlocale.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rlocale.py Mon Jun 7 22:25:03 2010 @@ -152,6 +152,14 @@ _lconv = lltype.Ptr(cConfig.lconv) localeconv = external('localeconv', [], _lconv) +def numeric_formatting(): + """Specialized function to get formatting for numbers""" + conv = localeconv() + decimal_point = rffi.charp2str(conv.c_decimal_point) + thousands_sep = rffi.charp2str(conv.c_thousands_sep) + grouping = rffi.charp2str(conv.c_grouping) + return decimal_point, thousands_sep, grouping + _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP) def setlocale(category, locale): Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py Mon Jun 7 22:25:03 2010 @@ -4,7 +4,7 @@ import py import locale as cpython_locale from pypy.rlib.rlocale import setlocale, LC_ALL, LocaleError, isupper, \ - islower, isalpha, tolower, isalnum + islower, isalpha, tolower, isalnum, numeric_formatting class TestLocale(object): def setup_class(cls): @@ -27,4 +27,9 @@ assert not isalpha(ord(" ")) assert isalnum(ord("1")) assert tolower(ord("A")) == ord("a") - + +def test_numeric_formatting(): + dec, th, grouping = numeric_formatting() + assert isinstance(dec, str) + assert isinstance(th, str) + assert isinstance(grouping, str) From afa at codespeak.net Tue Jun 8 00:33:43 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 00:33:43 +0200 (CEST) Subject: [pypy-svn] r75186 - pypy/trunk/pypy/module/cpyext Message-ID: <20100607223343.181CB282BDB@codespeak.net> Author: afa Date: Tue Jun 8 00:33:40 2010 New Revision: 75186 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Fix translation Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 8 00:33:40 2010 @@ -181,7 +181,7 @@ """ if error is _NOT_SPECIFIED: if restype is PyObject: - error = lltype.nullptr(PyObject.TO) + error = lltype.nullptr(restype.TO) elif restype is lltype.Void: error = CANNOT_FAIL if type(error) is int: @@ -251,7 +251,7 @@ raise state = space.fromcache(State) state.set_exception(e) - if restype is PyObject: + if is_PyObject(restype): return None else: return api_function.error_value @@ -470,9 +470,9 @@ assert len(args) == len(callable.api_func.argtypes) for i, (typ, is_wrapped) in argtypes_enum_ui: arg = args[i] - if typ is PyObject and is_wrapped: + if is_PyObject(typ) and is_wrapped: if arg: - arg_conv = from_ref(space, arg) + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) else: arg_conv = None else: From afa at codespeak.net Tue Jun 8 01:53:55 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 01:53:55 +0200 (CEST) Subject: [pypy-svn] r75187 - pypy/trunk/pypy/module/cpyext Message-ID: <20100607235355.D12A1282BDB@codespeak.net> Author: afa Date: Tue Jun 8 01:53:54 2010 New Revision: 75187 Modified: pypy/trunk/pypy/module/cpyext/listobject.py pypy/trunk/pypy/module/cpyext/sequence.py pypy/trunk/pypy/module/cpyext/stringobject.py pypy/trunk/pypy/module/cpyext/unicodeobject.py Log: Remove 64bit compatibility sentence from docstrings Modified: pypy/trunk/pypy/module/cpyext/listobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/listobject.py (original) +++ pypy/trunk/pypy/module/cpyext/listobject.py Tue Jun 8 01:53:54 2010 @@ -72,9 +72,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyList_GET_SIZE(space, w_list): """Macro form of PyList_Size() without error checking. - - This macro returned an int. This might require changes in your - code for properly supporting 64-bit systems.""" + """ assert isinstance(w_list, W_ListObject) return len(w_list.wrappeditems) @@ -83,9 +81,7 @@ def PyList_Size(space, ref): """Return the length of the list object in list; this is equivalent to len(list) on a list object. - - This function returned an int. This might require changes in - your code for properly supporting 64-bit systems.""" + """ if not PyList_Check(space, ref): raise OperationError(space.w_TypeError, space.wrap("expected list object")) Modified: pypy/trunk/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/sequence.py (original) +++ pypy/trunk/pypy/module/cpyext/sequence.py Tue Jun 8 01:53:54 2010 @@ -10,9 +10,7 @@ def PySequence_Repeat(space, w_obj, count): """Return the result of repeating sequence object o count times, or NULL on failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" + """ return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) Modified: pypy/trunk/pypy/module/cpyext/stringobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stringobject.py (original) +++ pypy/trunk/pypy/module/cpyext/stringobject.py Tue Jun 8 01:53:54 2010 @@ -180,9 +180,7 @@ the address in *string may differ from its input value. If the reallocation fails, the original string object at *string is deallocated, *string is set to NULL, a memory exception is set, and -1 is returned. - - This function used an int type for newsize. This might - require changes in your code for properly supporting 64-bit systems.""" + """ # XXX always create a new string so far py_str = rffi.cast(PyStringObject, ref[0]) if not py_str.c_buffer: Modified: pypy/trunk/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/unicodeobject.py Tue Jun 8 01:53:54 2010 @@ -105,10 +105,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyUnicode_GET_SIZE(space, w_obj): """Return the size of the object. o has to be a PyUnicodeObject (not - checked). - - This function returned an int type. This might require changes - in your code for properly supporting 64-bit systems.""" + checked).""" assert isinstance(w_obj, unicodeobject.W_UnicodeObject) return space.int_w(space.len(w_obj)) From fijal at codespeak.net Tue Jun 8 05:17:53 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Jun 2010 05:17:53 +0200 (CEST) Subject: [pypy-svn] r75188 - pypy/trunk/pypy/module/cpyext Message-ID: <20100608031753.5F7C1282BDB@codespeak.net> Author: fijal Date: Tue Jun 8 05:17:51 2010 New Revision: 75188 Modified: pypy/trunk/pypy/module/cpyext/unicodeobject.py Log: Rename arguments to something saner. Also fix a typo Modified: pypy/trunk/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/unicodeobject.py Tue Jun 8 05:17:51 2010 @@ -187,7 +187,7 @@ return 0 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject) -def PyUnicode_AsEncodedString(space, w_unicode, encoding, errors): +def PyUnicode_AsEncodedString(space, w_unicode, llencoding, llerrors): """Encode a Unicode object and return the result as Python string object. encoding and errors have the same meaning as the parameters of the same name in the Unicode encode() method. The codec to be used is looked up using @@ -196,12 +196,12 @@ if not PyUnicode_Check(space, w_unicode): PyErr_BadArgument(space) - w_encoding = w_errors = None - if encoding: - w_encoding = rffi.charp2str(encoding) - if errors: - w_errors = rffi.charp2str(encoding) - return unicodetype.encode_object(space, w_unicode, w_encoding, w_errors) + encoding = errors = None + if llencoding: + encoding = rffi.charp2str(llencoding) + if llerrors: + errors = rffi.charp2str(llerrors) + return unicodetype.encode_object(space, w_unicode, encoding, errors) @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject) def PyUnicode_FromUnicode(space, wchar_p, length): From fijal at codespeak.net Tue Jun 8 05:20:13 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Jun 2010 05:20:13 +0200 (CEST) Subject: [pypy-svn] r75189 - pypy/trunk/pypy/module/cpyext/test Message-ID: <20100608032013.AC2C6282BDB@codespeak.net> Author: fijal Date: Tue Jun 8 05:20:12 2010 New Revision: 75189 Modified: pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py Log: Add a test Modified: pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py Tue Jun 8 05:20:12 2010 @@ -49,7 +49,14 @@ space.newtuple([1, 2, 3]), None, None) self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString, space.wrap(''), None, None) + ascii = rffi.str2charp('ascii') + replace = rffi.str2charp('replace') + encoded = api.PyUnicode_AsEncodedString(space.wrap(u'sp?m'), + ascii, replace) + assert space.unwrap(encoded) == 'sp?m' rffi.free_charp(utf_8) + rffi.free_charp(replace) + rffi.free_charp(ascii) buf = rffi.unicode2wcharp(u"12345") api.PyUnicode_AsWideChar(space.wrap(u'longword'), buf, 5) From dan at codespeak.net Tue Jun 8 06:10:48 2010 From: dan at codespeak.net (dan at codespeak.net) Date: Tue, 8 Jun 2010 06:10:48 +0200 (CEST) Subject: [pypy-svn] r75190 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100608041048.F0F00282BDB@codespeak.net> Author: dan Date: Tue Jun 8 06:10:46 2010 New Revision: 75190 Modified: pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py pypy/trunk/pypy/module/cpyext/unicodeobject.py Log: Added PyUnicode_AsUnicodeEscapeString() and test. Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Tue Jun 8 06:10:46 2010 @@ -2967,13 +2967,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsUnicodeEscapeString(space, unicode): - """Encode a Unicode object using Unicode-Escape and return the result as Python - string object. Error handling is "strict". Return NULL if an exception was - raised by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject) def PyUnicode_DecodeRawUnicodeEscape(space, s, size, errors): """Create a Unicode object by decoding size bytes of the Raw-Unicode-Escape Modified: pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py Tue Jun 8 06:10:46 2010 @@ -150,3 +150,14 @@ rffi.free_wcharp(wbuf) assert space.type(w_str) is space.w_str assert space.str_w(w_str) == "abc?" + + def test_escape(self, space, api): + def test(ustr): + w_ustr = space.wrap(ustr.decode('Unicode-Escape')) + result = api.PyUnicode_AsUnicodeEscapeString(w_ustr) + assert space.eq_w(space.wrap(ustr), result) + + test('\\u674f\\u7f8e') + test('\\u0105\\u0107\\u017c\\u017a') + test('El Ni\\xf1o') + Modified: pypy/trunk/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/unicodeobject.py Tue Jun 8 06:10:46 2010 @@ -203,6 +203,16 @@ errors = rffi.charp2str(llerrors) return unicodetype.encode_object(space, w_unicode, encoding, errors) + at cpython_api([PyObject], PyObject) +def PyUnicode_AsUnicodeEscapeString(space, w_unicode): + """Encode a Unicode object using Unicode-Escape and return the result as Python + string object. Error handling is "strict". Return NULL if an exception was + raised by the codec.""" + if not PyUnicode_Check(space, w_unicode): + PyErr_BadArgument(space) + + return unicodetype.encode_object(space, w_unicode, 'unicode-escape', 'strict') + @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject) def PyUnicode_FromUnicode(space, wchar_p, length): """Create a Unicode Object from the Py_UNICODE buffer u of the given size. u From afa at codespeak.net Tue Jun 8 13:20:40 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 13:20:40 +0200 (CEST) Subject: [pypy-svn] r75191 - pypy/trunk/pypy/module/cpyext Message-ID: <20100608112040.7BD50282BD4@codespeak.net> Author: afa Date: Tue Jun 8 13:20:38 2010 New Revision: 75191 Modified: pypy/trunk/pypy/module/cpyext/TODO Log: This is resolved now. Modified: pypy/trunk/pypy/module/cpyext/TODO ============================================================================== --- pypy/trunk/pypy/module/cpyext/TODO (original) +++ pypy/trunk/pypy/module/cpyext/TODO Tue Jun 8 13:20:38 2010 @@ -15,8 +15,6 @@ - Fix GIL handling (e.g. after releasing the GIL, GC operations might occur in savethreads). - - Export pointers where pointers are expected, i.e. kill the "#define PyExc_OSError &PyExc_OSError" hack. - - refactor management of py_objects_r2w and py_objects_w2r, this can probably be expressed in terms of _PyObject_GC_TRACK macros. From afa at codespeak.net Tue Jun 8 14:58:56 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 14:58:56 +0200 (CEST) Subject: [pypy-svn] r75192 - in pypy/trunk/pypy/module/cpyext: . include test Message-ID: <20100608125856.9F8C8282BF9@codespeak.net> Author: afa Date: Tue Jun 8 14:58:54 2010 New Revision: 75192 Modified: pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/datetime.py pypy/trunk/pypy/module/cpyext/include/datetime.h pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Add the PyDateTime_CAPI structure, that holds common types from the datetime module. 2 caveats: - the datetime module is now pre-loaded in pypy-c - api.py really needs some refactoring. Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Tue Jun 8 14:58:54 2010 @@ -315,6 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -360,7 +361,9 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr}[ctype] + from pypy.module.cpyext.datetime import PyDateTime_CAPI + return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, + "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) @@ -506,13 +509,14 @@ % (callable.__name__,)) retval = error_value - elif callable.api_func.restype is PyObject: + elif is_PyObject(callable.api_func.restype): if result is None: retval = make_ref(space, None) elif isinstance(result, BorrowPair): retval = result.get_ref(space) elif not rffi._isllptr(result): - retval = make_ref(space, result) + retval = rffi.cast(callable.api_func.restype, + make_ref(space, result)) else: retval = result elif callable.api_func.restype is not lltype.Void: @@ -612,8 +616,10 @@ for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - if name.startswith('PyExc_'): - global_objects.append('%s %s;' % (typ[:-1], '_' + name)) + if typ == 'PyDateTime_CAPI*': + global_objects.append('%s _%s;' % (typ, name)) + elif name.startswith('PyExc_'): + global_objects.append('%s _%s;' % (typ[:-1], name)) else: global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) @@ -653,7 +659,13 @@ name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), + if typ == 'PyObject*': + value = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + value = w_obj + else: + assert False, "Unknown static pointer: %s %s" % (typ, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_'): @@ -804,6 +816,9 @@ elif name.startswith('PyExc_'): structs.append('extern PyTypeObject _%s;' % (name,)) structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) + elif typ == 'PyDateTime_CAPI*': + structs.append('extern %s _%s;' % (typ[:-1], name)) + structs.append('%s %s = &_%s;' % (typ, name, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -853,7 +868,13 @@ name = '_' + name from pypy.module import cpyext w_obj = eval(expr) - struct_ptr = make_ref(space, w_obj) + if typ in ('PyObject*', 'PyTypeObject*'): + struct_ptr = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + struct_ptr = w_obj + name = '_' + name + else: + assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) @@ -946,7 +967,7 @@ assert len(args) == len(FT.ARGS) for i, ARG in unrolling_arg_types: arg = args[i] - if ARG is PyObject: + if is_PyObject(ARG): if arg is None: boxed_args += (lltype.nullptr(PyObject.TO),) elif isinstance(arg, W_Root): @@ -969,7 +990,7 @@ finally: state.swap_borrow_container(old_container) - if RESULT_TYPE is PyObject: + if is_PyObject(RESULT_TYPE): if result is None: ret = result elif isinstance(result, W_Root): Modified: pypy/trunk/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/datetime.py Tue Jun 8 14:58:54 2010 @@ -1,14 +1,42 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import PyObject +from pypy.module.cpyext.pyobject import PyObject, make_ref from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import +from pypy.module.cpyext.typeobject import PyTypeObjectPtr from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_renamer # API import function - at cpython_api([], lltype.Void) +PyDateTime_CAPI = cpython_struct( + 'PyDateTime_CAPI', + (('DateType', PyTypeObjectPtr), + ('DateTimeType', PyTypeObjectPtr), + ('TimeType', PyTypeObjectPtr), + ('DeltaType', PyTypeObjectPtr), + )) + +def build_datetime_api(space): + w_datetime = PyImport_Import(space, space.wrap("datetime")) + datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw') + + w_type = space.getattr(w_datetime, space.wrap("date")) + datetimeAPI.c_DateType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("datetime")) + datetimeAPI.c_DateTimeType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("time")) + datetimeAPI.c_TimeType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("timedelta")) + datetimeAPI.c_DeltaType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + + return datetimeAPI + + at cpython_api([], PyObject) def _PyDateTime_Import(space): return Modified: pypy/trunk/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/datetime.h (original) +++ pypy/trunk/pypy/module/cpyext/include/datetime.h Tue Jun 8 14:58:54 2010 @@ -4,6 +4,16 @@ extern "C" { #endif +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; +} PyDateTime_CAPI; + +PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; #define PyDateTime_IMPORT _PyDateTime_Import() typedef struct { Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Tue Jun 8 14:58:54 2010 @@ -79,3 +79,21 @@ w_date = api.PyDateTime_FromTimestamp(w_args) date = datetime.datetime.fromtimestamp(0) assert space.unwrap(space.str(w_date)) == str(date) + +class AppTestDatetime(AppTestCpythonExtensionBase): + def test_CAPI(self): + module = self.import_extension('foo', [ + ("get_types", "METH_NOARGS", + """ + return PyTuple_Pack(4, + PyDateTimeAPI->DateType, + PyDateTimeAPI->DateTimeType, + PyDateTimeAPI->TimeType, + PyDateTimeAPI->DeltaType); + """), + ]) + import datetime + assert module.get_types() == (datetime.date, + datetime.datetime, + datetime.time, + datetime.timedelta) From afa at codespeak.net Tue Jun 8 15:03:44 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 15:03:44 +0200 (CEST) Subject: [pypy-svn] r75193 - pypy/trunk/pypy/module/cpyext/patches Message-ID: <20100608130344.13BBE282BF9@codespeak.net> Author: afa Date: Tue Jun 8 15:03:42 2010 New Revision: 75193 Added: pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch (contents, props changed) Log: cx_Oracle now works, with this patch. Added: pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch Tue Jun 8 15:03:42 2010 @@ -0,0 +1,60 @@ +Index: cx_Oracle.c +=================================================================== +--- cx_Oracle.c (r?vision 333) ++++ cx_Oracle.c (copie de travail) +@@ -65,6 +65,13 @@ + #define CXORA_BASE_EXCEPTION PyExc_StandardError + #endif + ++// define missing PyDateTime_DELTA macros ++#ifndef PYPY_VERSION ++PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) ++PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) ++PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds) ++#endif ++ + // define simple construct for determining endianness of the platform + // Oracle uses native encoding with OCI_UTF16 but bails when a BOM is written + #define IS_LITTLE_ENDIAN (int)*(unsigned char*) &one +@@ -138,6 +145,7 @@ + *exception = PyErr_NewException(buffer, baseException, NULL); + if (!*exception) + return -1; ++ Py_INCREF(*exception); + return PyModule_AddObject(module, name, *exception); + } + +Index: IntervalVar.c +=================================================================== +--- IntervalVar.c (r?vision 333) ++++ IntervalVar.c (copie de travail) +@@ -121,7 +121,7 @@ + unsigned pos, // array position to set + PyObject *value) // value to set + { +- sb4 hours, minutes, seconds; ++ sb4 days, hours, minutes, seconds, microseconds; + PyDateTime_Delta *delta; + sword status; + +@@ -131,13 +131,16 @@ + } + + delta = (PyDateTime_Delta*) value; +- hours = (sb4) delta->seconds / 3600; +- seconds = delta->seconds - hours * 3600; ++ days = PyDateTime_DELTA_GET_DAYS(delta); ++ seconds = PyDateTime_DELTA_GET_SECONDS(delta); ++ hours = (sb4) seconds / 3600; ++ seconds -= hours * 3600; + minutes = (sb4) seconds / 60; + seconds -= minutes * 60; ++ microseconds = PyDateTime_DELTA_GET_MICROSECONDS(delta); + status = OCIIntervalSetDaySecond(var->environment->handle, +- var->environment->errorHandle, delta->days, hours, minutes, +- seconds, delta->microseconds, var->data[pos]); ++ var->environment->errorHandle, days, hours, minutes, ++ seconds, microseconds, var->data[pos]); + if (Environment_CheckForError(var->environment, status, + "IntervalVar_SetValue()") < 0) + return -1; From afa at codespeak.net Tue Jun 8 15:04:08 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 15:04:08 +0200 (CEST) Subject: [pypy-svn] r75194 - pypy/trunk/pypy/module/cpyext/patches Message-ID: <20100608130408.E65D3282BF9@codespeak.net> Author: afa Date: Tue Jun 8 15:04:07 2010 New Revision: 75194 Modified: pypy/trunk/pypy/module/cpyext/patches/mysqldb.patch (props changed) pypy/trunk/pypy/module/cpyext/patches/numpy.patch (props changed) pypy/trunk/pypy/module/cpyext/patches/pycairo.patch (props changed) Log: fixeol From afa at codespeak.net Tue Jun 8 16:04:03 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 16:04:03 +0200 (CEST) Subject: [pypy-svn] r75195 - pypy/trunk/lib-python/modified-2.5.2/distutils/command Message-ID: <20100608140403.5655F282BDB@codespeak.net> Author: afa Date: Tue Jun 8 16:04:01 2010 New Revision: 75195 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py Log: Revert part of the change, and use the same name as CPython for the import library Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py Tue Jun 8 16:04:01 2010 @@ -647,7 +647,9 @@ """ # The python library is always needed on Windows. if sys.platform == "win32": - pythonlib = 'libpypy-c.exe' + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] From afa at codespeak.net Tue Jun 8 16:31:44 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 16:31:44 +0200 (CEST) Subject: [pypy-svn] r75196 - in pypy/trunk/lib-python/modified-2.5.2/distutils: . tests Message-ID: <20100608143144.2BAA8282BDB@codespeak.net> Author: afa Date: Tue Jun 8 16:31:42 2010 New Revision: 75196 Added: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py (contents, props changed) Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/msvccompiler.py Log: On Windows, correctly retrieve the version of the compiler used to compile the interpreter. Don't rely on sys.version (pypy does not indicates the compiler version), directly fetch the manifest embedded in the program. Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/msvccompiler.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/msvccompiler.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/msvccompiler.py Tue Jun 8 16:31:42 2010 @@ -159,14 +159,60 @@ s = s.replace(k, v) return s +def get_manifests(): + """Retrieves the manifest(s) embedded in the current executable""" + import ctypes.wintypes + EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA + EnumResourceNameCallback = ctypes.WINFUNCTYPE( + ctypes.wintypes.BOOL, + ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, + ctypes.wintypes.LONG, ctypes.wintypes.LONG) + FindResource = ctypes.windll.kernel32.FindResourceA + LoadResource = ctypes.windll.kernel32.LoadResource + FreeResource = ctypes.windll.kernel32.FreeResource + SizeofResource = ctypes.windll.kernel32.SizeofResource + LockResource = ctypes.windll.kernel32.LockResource + UnlockResource = lambda x: None # hehe + + manifests = [] + + def callback(hModule, lpType, lpName, lParam): + hResource = FindResource(hModule, lpName, lpType) + size = SizeofResource(hModule, hResource) + hData = LoadResource(hModule, hResource) + try: + ptr = LockResource(hData) + try: + manifests.append(ctypes.string_at(ptr, size)) + finally: + UnlockResource(hData) + finally: + FreeResource(hData) + return True + + hModule = None # main executable + RT_MANIFEST = 24 # from WinUser.h + EnumResourceNames(hModule, RT_MANIFEST, + EnumResourceNameCallback(callback), None) + return manifests + def get_build_version(): """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. """ + try: + manifests = get_manifests() + for manifest in manifests: + match = re.search('"Microsoft.VC([0-9]+).CRT"', manifest) + if match: + return int(match.group(1)) / 10.0 + except BaseException: + pass + # No manifest embedded, use default compiler version return 9.0 +def get_build_architecture(): + return 'Intel' + def normalize_and_reduce_paths(paths): """Return a list of normalized paths with duplicates removed. Added: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py ============================================================================== --- (empty file) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py Tue Jun 8 16:31:42 2010 @@ -0,0 +1,18 @@ +import unittest +from distutils.msvccompiler import get_manifests + +class MsvcCompilerTestCase(unittest.TestCase): + def test_get_manifests(self): + manifests = get_manifests() + self.assert_(manifests) + for manifest in manifests: + if '"Microsoft.VC' in manifest: + break + else: + self.fail("could not find a suitable manifest") + +def test_suite(): + return unittest.makeSuite(MsvcCompilerTestCase) + +if __name__ == "__main__": + unittest.main(defaultTest="test_suite") From afa at codespeak.net Tue Jun 8 16:32:24 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 16:32:24 +0200 (CEST) Subject: [pypy-svn] r75197 - pypy/trunk/dotviewer Message-ID: <20100608143224.26003282BDB@codespeak.net> Author: afa Date: Tue Jun 8 16:32:22 2010 New Revision: 75197 Modified: pypy/trunk/dotviewer/graphparse.py Log: Don't close_fds on Windows, it does not work anyway. Modified: pypy/trunk/dotviewer/graphparse.py ============================================================================== --- pypy/trunk/dotviewer/graphparse.py (original) +++ pypy/trunk/dotviewer/graphparse.py Tue Jun 8 16:32:22 2010 @@ -47,7 +47,8 @@ else: cmdline = 'neato -Tplain' #print >> sys.stderr, '* running:', cmdline - p = subprocess.Popen(cmdline, shell=True, close_fds=True, + close_fds = sys.platform != 'win32' + p = subprocess.Popen(cmdline, shell=True, close_fds=close_fds, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (child_in, child_out) = (p.stdin, p.stdout) try: From afa at codespeak.net Tue Jun 8 16:48:45 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 16:48:45 +0200 (CEST) Subject: [pypy-svn] r75198 - in pypy/branch/cpyext-init-cleanup: . dotviewer lib-python lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command lib-python/modified-2.5.2/distutils/tests py/_code pypy/annotation pypy/annotation/test pypy/doc pypy/jit/metainterp pypy/jit/metainterp/test pypy/module/_codecs pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/patches pypy/module/cpyext/test pypy/module/imp pypy/module/imp/test pypy/module/sys pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/test pypy/tool pypy/tool/pytest pypy/tool/pytest/test pypy/tool/test pypy/translator/c/test Message-ID: <20100608144845.7EB4D282BDB@codespeak.net> Author: afa Date: Tue Jun 8 16:48:41 2010 New Revision: 75198 Added: pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py - copied unchanged from r75197, pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/cx_Oracle.patch - copied unchanged from r75197, pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py - copied, changed from r75197, pypy/trunk/pypy/module/cpyext/test/test_translate.py pypy/branch/cpyext-init-cleanup/pypy/tool/test/test_sourcetools.py - copied unchanged from r75197, pypy/trunk/pypy/tool/test/test_sourcetools.py Modified: pypy/branch/cpyext-init-cleanup/ (props changed) pypy/branch/cpyext-init-cleanup/dotviewer/graphparse.py pypy/branch/cpyext-init-cleanup/lib-python/conftest.py pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/msvccompiler.py pypy/branch/cpyext-init-cleanup/py/_code/source.py pypy/branch/cpyext-init-cleanup/pypy/annotation/binaryop.py pypy/branch/cpyext-init-cleanup/pypy/annotation/builtin.py pypy/branch/cpyext-init-cleanup/pypy/annotation/classdef.py pypy/branch/cpyext-init-cleanup/pypy/annotation/test/test_annrpython.py pypy/branch/cpyext-init-cleanup/pypy/doc/objspace.txt pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/optimizeopt.py pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/pyjitpl.py pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/test/test_optimizeopt.py pypy/branch/cpyext-init-cleanup/pypy/module/_codecs/interp_codecs.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/TODO pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/boost.patch pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/mysqldb.patch (props changed) pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/numpy.patch (props changed) pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/pycairo.patch (props changed) pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubs.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/foo.c pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_datetime.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_longobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sequence.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sliceobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_typeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_unicodeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/imp/importing.py pypy/branch/cpyext-init-cleanup/pypy/module/imp/test/test_import.py pypy/branch/cpyext-init-cleanup/pypy/module/sys/__init__.py pypy/branch/cpyext-init-cleanup/pypy/module/sys/interp_encoding.py pypy/branch/cpyext-init-cleanup/pypy/objspace/std/formatting.py pypy/branch/cpyext-init-cleanup/pypy/objspace/std/test/test_stringformat.py pypy/branch/cpyext-init-cleanup/pypy/objspace/std/unicodetype.py pypy/branch/cpyext-init-cleanup/pypy/rlib/rarithmetic.py pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rarithmetic.py pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rlocale.py pypy/branch/cpyext-init-cleanup/pypy/rpython/lltypesystem/rstr.py pypy/branch/cpyext-init-cleanup/pypy/rpython/rbuiltin.py pypy/branch/cpyext-init-cleanup/pypy/rpython/test/test_rbuiltin.py pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/appsupport.py pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/test/test_appsupport.py pypy/branch/cpyext-init-cleanup/pypy/tool/sourcetools.py pypy/branch/cpyext-init-cleanup/pypy/translator/c/test/test_standalone.py Log: Merge from trunk Modified: pypy/branch/cpyext-init-cleanup/dotviewer/graphparse.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/dotviewer/graphparse.py (original) +++ pypy/branch/cpyext-init-cleanup/dotviewer/graphparse.py Tue Jun 8 16:48:41 2010 @@ -47,7 +47,8 @@ else: cmdline = 'neato -Tplain' #print >> sys.stderr, '* running:', cmdline - p = subprocess.Popen(cmdline, shell=True, close_fds=True, + close_fds = sys.platform != 'win32' + p = subprocess.Popen(cmdline, shell=True, close_fds=close_fds, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (child_in, child_out) = (p.stdin, p.stdout) try: Modified: pypy/branch/cpyext-init-cleanup/lib-python/conftest.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/lib-python/conftest.py (original) +++ pypy/branch/cpyext-init-cleanup/lib-python/conftest.py Tue Jun 8 16:48:41 2010 @@ -520,11 +520,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -532,7 +535,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): Modified: pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/command/build_ext.py Tue Jun 8 16:48:41 2010 @@ -647,7 +647,9 @@ """ # The python library is always needed on Windows. if sys.platform == "win32": - pythonlib = 'libpypy-c.exe' + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] Modified: pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/msvccompiler.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/msvccompiler.py (original) +++ pypy/branch/cpyext-init-cleanup/lib-python/modified-2.5.2/distutils/msvccompiler.py Tue Jun 8 16:48:41 2010 @@ -159,14 +159,60 @@ s = s.replace(k, v) return s +def get_manifests(): + """Retrieves the manifest(s) embedded in the current executable""" + import ctypes.wintypes + EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA + EnumResourceNameCallback = ctypes.WINFUNCTYPE( + ctypes.wintypes.BOOL, + ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, + ctypes.wintypes.LONG, ctypes.wintypes.LONG) + FindResource = ctypes.windll.kernel32.FindResourceA + LoadResource = ctypes.windll.kernel32.LoadResource + FreeResource = ctypes.windll.kernel32.FreeResource + SizeofResource = ctypes.windll.kernel32.SizeofResource + LockResource = ctypes.windll.kernel32.LockResource + UnlockResource = lambda x: None # hehe + + manifests = [] + + def callback(hModule, lpType, lpName, lParam): + hResource = FindResource(hModule, lpName, lpType) + size = SizeofResource(hModule, hResource) + hData = LoadResource(hModule, hResource) + try: + ptr = LockResource(hData) + try: + manifests.append(ctypes.string_at(ptr, size)) + finally: + UnlockResource(hData) + finally: + FreeResource(hData) + return True + + hModule = None # main executable + RT_MANIFEST = 24 # from WinUser.h + EnumResourceNames(hModule, RT_MANIFEST, + EnumResourceNameCallback(callback), None) + return manifests + def get_build_version(): """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. """ + try: + manifests = get_manifests() + for manifest in manifests: + match = re.search('"Microsoft.VC([0-9]+).CRT"', manifest) + if match: + return int(match.group(1)) / 10.0 + except BaseException: + pass + # No manifest embedded, use default compiler version return 9.0 +def get_build_architecture(): + return 'Intel' + def normalize_and_reduce_paths(paths): """Return a list of normalized paths with duplicates removed. Modified: pypy/branch/cpyext-init-cleanup/py/_code/source.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/py/_code/source.py (original) +++ pypy/branch/cpyext-init-cleanup/py/_code/source.py Tue Jun 8 16:48:41 2010 @@ -17,6 +17,7 @@ """ a immutable object holding a source code fragment, possibly deindenting it. """ + _compilecounter = 0 def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -195,10 +196,12 @@ if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno + base = "<%d-codegen " % self._compilecounter + self.__class__._compilecounter += 1 if not filename: - filename = '' % (fn, lineno) + filename = base + '%s:%d>' % (fn, lineno) else: - filename = '' % (filename, fn, lineno) + filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) Modified: pypy/branch/cpyext-init-cleanup/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/annotation/binaryop.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/annotation/binaryop.py Tue Jun 8 16:48:41 2010 @@ -442,7 +442,7 @@ return SomeUnicodeString() class __extend__(pairtype(SomeString, SomeUnicodeString), - pairtype(SomeString, SomeUnicodeString)): + pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") Modified: pypy/branch/cpyext-init-cleanup/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/annotation/builtin.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/annotation/builtin.py Tue Jun 8 16:48:41 2010 @@ -272,6 +272,12 @@ def OSError_init(s_self, *args): pass +def UnicodeDecodeError_init(s_self, *args): + pass + +def UnicodeEncodeError_init(s_self, *args): + pass + def WindowsError_init(s_self, *args): pass @@ -390,6 +396,8 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) +BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init +BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/cpyext-init-cleanup/pypy/annotation/classdef.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/annotation/classdef.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/annotation/classdef.py Tue Jun 8 16:48:41 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString + SomeString, SomeUnicodeString from pypy.annotation import description @@ -439,6 +439,16 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, + UnicodeDecodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeString(), + 'encoding': SomeString(), + 'reason': SomeString()}, + UnicodeEncodeError: {'end': SomeInteger(), + 'start': SomeInteger(), + 'object': SomeUnicodeString(), + 'encoding': SomeString(), + 'reason': SomeString()} } try: Modified: pypy/branch/cpyext-init-cleanup/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/annotation/test/test_annrpython.py Tue Jun 8 16:48:41 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_unicode_decode_error(self): + def f(): + try: + raise UnicodeDecodeError("x", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + return ude.end + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInteger) + def g(n): return [0,1,2,n] Modified: pypy/branch/cpyext-init-cleanup/pypy/doc/objspace.txt ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/doc/objspace.txt (original) +++ pypy/branch/cpyext-init-cleanup/pypy/doc/objspace.txt Tue Jun 8 16:48:41 2010 @@ -552,7 +552,7 @@ A number of options for configuration is here in `traceconfig.py`_. -.. _`found here` : getting-started.html#tracing-bytecode-and-operations-on-objects +.. _`found here` : getting-started-dev.html#tracing-bytecode-and-operations-on-objects .. _`Abstract Interpretation`: theory.html#abstract-interpretation .. _`traceconfig.py`: ../tool/traceconfig.py Modified: pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/optimizeopt.py Tue Jun 8 16:48:41 2010 @@ -1066,7 +1066,7 @@ return None def emitting_operation(self, op): - if op.has_no_side_effect(): + if op.opnum != rop.CALL_PURE and op.has_no_side_effect(): return if op.is_ovf(): return @@ -1079,6 +1079,7 @@ return if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or + opnum == rop.CALL_PURE or opnum == rop.CALL_ASSEMBLER): if opnum == rop.CALL_ASSEMBLER: effectinfo = None Modified: pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/pyjitpl.py Tue Jun 8 16:48:41 2010 @@ -1719,7 +1719,8 @@ self.history.record(rop.JUMP, exits, None) target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1729,7 +1730,8 @@ loop_tokens = sd.loop_tokens_exit_frame_with_exception_ref target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + raise GiveUp def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests Modified: pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/jit/metainterp/test/test_optimizeopt.py Tue Jun 8 16:48:41 2010 @@ -2586,6 +2586,16 @@ ''' self.optimize_loop(ops, 'Not, Not', ops) + def test_call_pure_invalidates_caches(self): + ops = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call_pure(p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + self.optimize_loop(ops, 'Not, Not', ops) + def test_vref_nonvirtual_nonescape(self): ops = """ [p1] Modified: pypy/branch/cpyext-init-cleanup/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/_codecs/interp_codecs.py Tue Jun 8 16:48:41 2010 @@ -2,6 +2,7 @@ from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder +from pypy.rlib.objectmodel import we_are_translated class CodecState(object): def __init__(self, space): @@ -52,6 +53,9 @@ return replace, newpos return unicode_call_errorhandler + def _freeze_(self): + assert not self.codec_search_path + return False def register_codec(space, w_search_function): """register(search_function) @@ -75,6 +79,8 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ + assert not (space.config.translating and not we_are_translated()), \ + "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() w_result = state.codec_search_cache.get(normalized_encoding, None) @@ -215,11 +221,8 @@ else: encoding = space.str_w(w_encoding) w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) - if space.is_true(w_encoder): - w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) - return space.getitem(w_res, space.wrap(0)) - else: - assert 0, "XXX, what to do here?" + w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) + return space.getitem(w_res, space.wrap(0)) encode.unwrap_spec = [ObjSpace, W_Root, W_Root, str] def buffer_encode(space, s, errors='strict'): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/TODO ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/TODO (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/TODO Tue Jun 8 16:48:41 2010 @@ -15,8 +15,6 @@ - Fix GIL handling (e.g. after releasing the GIL, GC operations might occur in savethreads). - - Export pointers where pointers are expected, i.e. kill the "#define PyExc_OSError &PyExc_OSError" hack. - - refactor management of py_objects_r2w and py_objects_w2r, this can probably be expressed in terms of _PyObject_GC_TRACK macros. Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 16:48:41 2010 @@ -11,6 +11,7 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rlib.objectmodel import we_are_translated from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.gensupp import NameManager from pypy.tool.udir import udir from pypy.translator import platform from pypy.module.cpyext.state import State @@ -136,14 +137,18 @@ # the error value specifed in the API. # +cpyext_namespace = NameManager('cpyext_') + class ApiFunction(BaseApiObject): - def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED): + def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, + c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error + self.c_name = c_name # extract the signature from user code object from pypy.interpreter import pycode @@ -178,6 +183,8 @@ wrapper = make_wrapper(space, self.callable) self._wrapper = wrapper wrapper.relax_sig_check = True + if self.c_name is not None: + wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): @@ -193,7 +200,7 @@ """ if error is _NOT_SPECIFIED: if restype is PyObject: - error = lltype.nullptr(PyObject.TO) + error = lltype.nullptr(restype.TO) elif restype is lltype.Void: error = CANNOT_FAIL if type(error) is int: @@ -201,11 +208,16 @@ def decorate(func): func_name = func.func_name - api_function = ApiFunction(argtypes, restype, func, error) + if external: + c_name = None + else: + c_name = func_name + api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) func.api_func = api_function - assert func_name not in FUNCTIONS, "%s already registered" % func_name - assert func_name not in FUNCTIONS_STATIC + if external: + assert func_name not in FUNCTIONS, ( + "%s already registered" % func_name) if error is _NOT_SPECIFIED: raise ValueError("function %s has no return value for exceptions" @@ -258,7 +270,7 @@ raise state = space.fromcache(State) state.set_exception(e) - if restype is PyObject: + if is_PyObject(restype): return None else: return api_function.error_value @@ -280,8 +292,6 @@ unwrapper_raise = make_unwrapper(False) if external: FUNCTIONS[func_name] = api_function - else: - FUNCTIONS_STATIC[func_name] = api_function INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests return unwrapper_raise # used in 'normal' RPython code. return decorate @@ -296,7 +306,6 @@ INTERPLEVEL_API = {} FUNCTIONS = {} -FUNCTIONS_STATIC = {} SYMBOLS_C = [ 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse', 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords', @@ -325,6 +334,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -334,7 +344,7 @@ # Standard exceptions for exc_name in exceptions.Module.interpleveldefs.keys(): GLOBALS['PyExc_' + exc_name] = ( - 'PyObject*', + 'PyTypeObject*', 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, )) # Common types with their own struct @@ -370,7 +380,9 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr}[ctype] + from pypy.module.cpyext.datetime import PyDateTime_CAPI + return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, + "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) @@ -450,6 +462,7 @@ # Make the wrapper for the cases (1) and (2) def make_wrapper(space, callable): + "NOT_RPYTHON" names = callable.api_func.argnames argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, [name.startswith("w_") for name in names]))) @@ -471,9 +484,9 @@ assert len(args) == len(callable.api_func.argtypes) for i, (typ, is_wrapped) in argtypes_enum_ui: arg = args[i] - if typ is PyObject and is_wrapped: + if is_PyObject(typ) and is_wrapped: if arg: - arg_conv = from_ref(space, arg) + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) else: arg_conv = None else: @@ -507,13 +520,14 @@ % (callable.__name__,)) retval = error_value - elif callable.api_func.restype is PyObject: + elif is_PyObject(callable.api_func.restype): if result is None: retval = make_ref(space, None) elif isinstance(result, BorrowPair): retval = result.get_ref(space) elif not rffi._isllptr(result): - retval = make_ref(space, result) + retval = rffi.cast(callable.api_func.restype, + make_ref(space, result)) else: retval = result elif callable.api_func.restype is not lltype.Void: @@ -573,6 +587,7 @@ # back into Pypy space functions # Do not call this more than once per process def build_bridge(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -602,7 +617,12 @@ for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - global_objects.append('%s %s = NULL;' % (typ, name)) + if typ == 'PyDateTime_CAPI*': + global_objects.append('%s _%s;' % (typ, name)) + elif name.startswith('PyExc_'): + global_objects.append('%s _%s;' % (typ[:-1], name)) + else: + global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -622,7 +642,6 @@ # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) - pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # populate static data for name, (typ, expr) in GLOBALS.iteritems(): @@ -633,16 +652,31 @@ isptr = False else: isptr = True + if name.startswith('PyExc_'): + isptr = False + INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), + if typ == 'PyObject*': + value = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + value = w_obj + else: + assert False, "Unknown static pointer: %s %s" % (typ, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge,name) - py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + if name.startswith('PyPyExc_'): + # we already have the pointer + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) + else: + # we have a structure, get its address + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) w_type = space.type(w_obj) @@ -655,8 +689,12 @@ else: assert False, "Unknown static object: %s %s" % (typ, name) + pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') + # implement structure initialization code for name, func in FUNCTIONS.iteritems(): + if name.startswith('cpyext_'): # XXX hack + continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llpointer(space)), ctypes.c_void_p) @@ -665,6 +703,7 @@ return modulename.new(ext='') def generate_macros(export_symbols, rename=True, do_deref=True): + "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] for name in export_symbols: @@ -678,6 +717,8 @@ if not rename: newname = name pypy_macros.append('#define %s %s' % (name, newname)) + if name.startswith("PyExc_"): + pypy_macros.append('#define _%s _%s' % (name, newname)) renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols @@ -699,6 +740,7 @@ pypy_macros_h.write('\n'.join(pypy_macros)) def generate_decls_and_callbacks(db, export_symbols, api_struct=True): + "NOT_RPYTHON" # implement function callbacks and generate function decls functions = [] pypy_decls = [] @@ -726,6 +768,8 @@ if name.endswith('#'): name = name.replace("#", "") typ = typ.replace("*", "") + elif name.startswith('PyExc_'): + typ = 'PyObject*' pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) pypy_decls.append("#ifdef __cplusplus") @@ -738,6 +782,7 @@ return functions def build_eci(building_bridge, export_symbols, code): + "NOT_RPYTHON" # Build code and get pointer to the structure kwds = {} export_symbols_eci = export_symbols[:] @@ -760,6 +805,12 @@ for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): structs.append('%s %s;' % (typ[:-1], name[:-1])) + elif name.startswith('PyExc_'): + structs.append('extern PyTypeObject _%s;' % (name,)) + structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) + elif typ == 'PyDateTime_CAPI*': + structs.append('extern %s _%s;' % (typ[:-1], name)) + structs.append('%s %s = &_%s;' % (typ, name, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -785,6 +836,7 @@ def setup_library(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -803,9 +855,17 @@ # populate static data for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") + if name.startswith('PyExc_'): + name = '_' + name from pypy.module import cpyext w_obj = eval(expr) - struct_ptr = make_ref(space, w_obj) + if typ in ('PyObject*', 'PyTypeObject*'): + struct_ptr = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + struct_ptr = w_obj + name = '_' + name + else: + assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) @@ -813,8 +873,6 @@ for name, func in FUNCTIONS.iteritems(): deco = entrypoint("cpyext", func.argtypes, name, relax=True) deco(func._get_wrapper(space)) - for name, func in FUNCTIONS_STATIC.iteritems(): - func._get_wrapper(space).c_name = name setup_init_functions(eci) copy_header_files() @@ -900,7 +958,7 @@ assert len(args) == len(FT.ARGS) for i, ARG in unrolling_arg_types: arg = args[i] - if ARG is PyObject: + if is_PyObject(ARG): if arg is None: boxed_args += (lltype.nullptr(PyObject.TO),) elif isinstance(arg, W_Root): @@ -923,7 +981,7 @@ finally: state.swap_borrow_container(old_container) - if RESULT_TYPE is PyObject: + if is_PyObject(RESULT_TYPE): if result is None: ret = result elif isinstance(result, W_Root): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py Tue Jun 8 16:48:41 2010 @@ -1,16 +1,248 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import PyObject -from pypy.module.cpyext.api import cpython_api +from pypy.module.cpyext.pyobject import PyObject, make_ref +from pypy.module.cpyext.api import ( + cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import +from pypy.module.cpyext.typeobject import PyTypeObjectPtr +from pypy.interpreter.error import OperationError +from pypy.tool.sourcetools import func_renamer - at cpython_api([], lltype.Void) -def PyDateTime_IMPORT(space): +# API import function + +PyDateTime_CAPI = cpython_struct( + 'PyDateTime_CAPI', + (('DateType', PyTypeObjectPtr), + ('DateTimeType', PyTypeObjectPtr), + ('TimeType', PyTypeObjectPtr), + ('DeltaType', PyTypeObjectPtr), + )) + +def build_datetime_api(space): + w_datetime = PyImport_Import(space, space.wrap("datetime")) + datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw') + + w_type = space.getattr(w_datetime, space.wrap("date")) + datetimeAPI.c_DateType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("datetime")) + datetimeAPI.c_DateTimeType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("time")) + datetimeAPI.c_TimeType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + w_type = space.getattr(w_datetime, space.wrap("timedelta")) + datetimeAPI.c_DeltaType = rffi.cast( + PyTypeObjectPtr, make_ref(space, w_type)) + + return datetimeAPI + + at cpython_api([], PyObject) +def _PyDateTime_Import(space): return - at cpython_api([rffi.INT, rffi.INT, rffi.INT, rffi.INT], PyObject) +PyDateTime_Date = PyObject +PyDateTime_Time = PyObject +PyDateTime_DateTime = PyObject + +PyDeltaObjectStruct = lltype.ForwardReference() +cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct) +PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct) + +# Check functions + +def make_check_function(func_name, type_name): + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name) + def check(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return isinstance(obj, datatype) + """ % (type_name,))) + except OperationError: + return 0 + + @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) + @func_renamer(func_name + "Exact") + def check_exact(space, w_obj): + try: + return space.is_true( + space.appexec([w_obj], """(obj): + from datetime import %s as datatype + return type(obj) is datatype + """ % (type_name,))) + except OperationError: + return 0 + +make_check_function("PyDateTime_Check", "datetime") +make_check_function("PyDate_Check", "date") +make_check_function("PyTime_Check", "time") +make_check_function("PyDelta_Check", "timedelta") + +# Constructors + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDate_FromDate(space, year, month, day): + """Return a datetime.date object with the specified year, month and day. + """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "date", + space.wrap(year), space.wrap(month), space.wrap(day)) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) def PyTime_FromTime(space, hour, minute, second, usecond): + """Return a ``datetime.time`` object with the specified hour, minute, second and + microsecond.""" + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) w_datetime = PyImport_Import(space, space.wrap("datetime")) return space.call_method( w_datetime, "time", space.wrap(hour), space.wrap(minute), space.wrap(second), space.wrap(usecond)) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): + """Return a datetime.datetime object with the specified year, month, day, hour, + minute, second and microsecond. + """ + year = rffi.cast(lltype.Signed, year) + month = rffi.cast(lltype.Signed, month) + day = rffi.cast(lltype.Signed, day) + hour = rffi.cast(lltype.Signed, hour) + minute = rffi.cast(lltype.Signed, minute) + second = rffi.cast(lltype.Signed, second) + usecond = rffi.cast(lltype.Signed, usecond) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "datetime", + space.wrap(year), space.wrap(month), space.wrap(day), + space.wrap(hour), space.wrap(minute), space.wrap(second), + space.wrap(usecond)) + raise NotImplementedError + + at cpython_api([PyObject], PyObject) +def PyDateTime_FromTimestamp(space, w_args): + """Create and return a new datetime.datetime object given an argument tuple + suitable for passing to datetime.datetime.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("datetime")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + + at cpython_api([PyObject], PyObject) +def PyDate_FromTimestamp(space, w_args): + """Create and return a new datetime.date object given an argument tuple + suitable for passing to datetime.date.fromtimestamp(). + """ + w_datetime = PyImport_Import(space, space.wrap("datetime")) + w_type = space.getattr(w_datetime, space.wrap("date")) + w_method = space.getattr(w_type, space.wrap("fromtimestamp")) + return space.call(w_method, w_args) + + at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) +def PyDelta_FromDSU(space, days, seconds, useconds): + """Return a datetime.timedelta object representing the given number of days, + seconds and microseconds. Normalization is performed so that the resulting + number of microseconds and seconds lie in the ranges documented for + datetime.timedelta objects. + """ + days = rffi.cast(lltype.Signed, days) + seconds = rffi.cast(lltype.Signed, seconds) + useconds = rffi.cast(lltype.Signed, useconds) + w_datetime = PyImport_Import(space, space.wrap("datetime")) + return space.call_method( + w_datetime, "timedelta", + space.wrap(days), space.wrap(seconds), space.wrap(useconds)) + +# Accessors + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_YEAR(space, w_obj): + """Return the year, as a positive int. + """ + return space.getattr(w_obj, space.wrap("year")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_MONTH(space, w_obj): + """Return the month, as an int from 1 through 12. + """ + return space.getattr(w_obj, space.wrap("month")) + + at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_GET_DAY(space, w_obj): + """Return the day, as an int from 1 through 31. + """ + return space.getattr(w_obj, space.wrap("day")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DATE_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_HOUR(space, w_obj): + """Return the hour, as an int from 0 through 23. + """ + return space.getattr(w_obj, space.wrap("hour")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MINUTE(space, w_obj): + """Return the minute, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("minute")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_SECOND(space, w_obj): + """Return the second, as an int from 0 through 59. + """ + return space.getattr(w_obj, space.wrap("second")) + + at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_TIME_GET_MICROSECOND(space, w_obj): + """Return the microsecond, as an int from 0 through 999999. + """ + return space.getattr(w_obj, space.wrap("microsecond")) + +# XXX these functions are not present in the Python API +# But it does not seem possible to expose a different structure +# for types defined in a python module like lib/datetime.py. + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_DAYS(space, w_obj): + return space.getattr(w_obj, space.wrap("days")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_SECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("seconds")) + + at cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj): + return space.getattr(w_obj, space.wrap("microseconds")) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h Tue Jun 8 16:48:41 2010 @@ -27,6 +27,7 @@ # endif # define Py_LOCAL_INLINE(type) static __inline type __fastcall #endif +#define DL_IMPORT(RTYPE) PyAPI_FUNC(RTYPE) #include @@ -95,6 +96,7 @@ #include "pycobject.h" #include "bufferobject.h" #include "sliceobject.h" +#include "datetime.h" #include "pystate.h" // XXX This shouldn't be included here Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h Tue Jun 8 16:48:41 2010 @@ -0,0 +1,26 @@ +#ifndef DATETIME_H +#define DATETIME_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; +} PyDateTime_CAPI; + +PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; +#define PyDateTime_IMPORT _PyDateTime_Import() + +typedef struct { + PyObject_HEAD +} PyDateTime_Delta; + +#ifdef __cplusplus +} +#endif +#endif Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py Tue Jun 8 16:48:41 2010 @@ -72,9 +72,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyList_GET_SIZE(space, w_list): """Macro form of PyList_Size() without error checking. - - This macro returned an int. This might require changes in your - code for properly supporting 64-bit systems.""" + """ assert isinstance(w_list, W_ListObject) return len(w_list.wrappeditems) @@ -83,9 +81,7 @@ def PyList_Size(space, ref): """Return the length of the list object in list; this is equivalent to len(list) on a list object. - - This function returned an int. This might require changes in - your code for properly supporting 64-bit systems.""" + """ if not PyList_Check(space, ref): raise OperationError(space.w_TypeError, space.wrap("expected list object")) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/boost.patch ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/boost.patch (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/patches/boost.patch Tue Jun 8 16:48:41 2010 @@ -1,16 +1,3 @@ -Index: libs/python/src/object/class.cpp -=================================================================== ---- libs/python/src/object/class.cpp 2009-11-13 01:40:01 +0100 -+++ libs/python/src/object/class.cpp 2010-06-02 23:25:08 +0200 -@@ -195,7 +195,7 @@ - - namespace objects - { --#if PY_VERSION_HEX < 0x03000000 -+#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) - // XXX Not sure why this run into compiling error in Python 3 - extern "C" - { Index: libs/python/src/object/function.cpp =================================================================== --- libs/python/src/object/function.cpp 2010-04-04 07:19:57 +0200 @@ -50,14 +37,21 @@ =================================================================== --- tools/build/v2/user-config.jam 2008-07-15 15:53:41 +0200 +++ tools/build/v2/user-config.jam 2010-06-02 23:46:13 +0200 -@@ -84,3 +84,9 @@ +@@ -84,3 +84,16 @@ # Configure with an explicit installation prefix. # using qt : /usr/opt/qt ; + ++# ------------------- ++# PyPy configuration. ++# ------------------- ++ ++PYPY_HOME = /home/amaury/trunk ; ++ +using python : 2.5 -+ : /home/amaury/trunk/pypy/pypy-c -+ : /home/amaury/trunk/pypy/module/cpyext/include -+ /home/amaury/trunk/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/pypy-c # interpreter ++ : $(PYPY_HOME)/pypy/module/cpyext/include # include paths ++ $(PYPY_HOME)/pypy/_interfaces ++ : $(PYPY_HOME)/pypy/_interfaces # library path + ; Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py Tue Jun 8 16:48:41 2010 @@ -2,9 +2,9 @@ from pypy.interpreter.baseobjspace import W_Root, SpaceCache from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, bootstrap_function, \ - PyObject, PyObjectP, ADDR, CANNOT_FAIL, \ - Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr +from pypy.module.cpyext.api import ( + cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR, + CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) from pypy.module.cpyext.state import State from pypy.objspace.std.typeobject import W_TypeObject from pypy.rlib.objectmodel import specialize, we_are_translated @@ -259,9 +259,9 @@ Allocates a PyObject, and fills its fields with info from the given intepreter object. """ + state = space.fromcache(RefcountState) w_type = space.type(w_obj) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) py_obj = state.get_from_lifeline(w_obj) if py_obj: Py_IncRef(space, py_obj) @@ -270,7 +270,6 @@ typedescr = get_typedescr(w_obj.typedef) py_obj = typedescr.allocate(space, w_type, itemcount=itemcount) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) state.set_lifeline(w_obj, py_obj) typedescr.attach(space, py_obj, w_obj) return py_obj @@ -329,7 +328,7 @@ # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) - if ref_type == ref: + if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py Tue Jun 8 16:48:41 2010 @@ -6,6 +6,12 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.objspace.std import listobject, tupleobject + at cpython_api([PyObject, Py_ssize_t], PyObject) +def PySequence_Repeat(space, w_obj, count): + """Return the result of repeating sequence object o count times, or NULL on + failure. This is the equivalent of the Python expression o * count. + """ + return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PySequence_Check(space, w_obj): @@ -91,6 +97,12 @@ return space.getitem(w_obj, space.wrap(i)) @cpython_api([PyObject], PyObject) +def PySequence_List(space, w_obj): + """Return a list object with the same contents as the arbitrary sequence o. The + returned list is guaranteed to be new.""" + return space.call_function(space.w_list, w_obj) + + at cpython_api([PyObject], PyObject) def PySequence_Tuple(space, w_obj): """Return a tuple object with the same contents as the arbitrary sequence o or NULL on failure. If o is a tuple, a new reference will be returned, Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py Tue Jun 8 16:48:41 2010 @@ -56,6 +56,12 @@ the same names. Any of the values may be NULL, in which case the None will be used for the corresponding attribute. Return NULL if the new object could not be allocated.""" + if w_start is None: + w_start = space.w_None + if w_stop is None: + w_stop = space.w_None + if w_step is None: + w_step = space.w_None return W_SliceObject(w_start, w_stop, w_step) @cpython_api([PySliceObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py Tue Jun 8 16:48:41 2010 @@ -5,15 +5,17 @@ from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc, - ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc) + ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc, + descrgetfunc, descrsetfunc) from pypy.module.cpyext.pyobject import from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.argument import Arguments from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name - +from pypy.rlib.objectmodel import specialize +from pypy.tool.sourcetools import func_renamer +from pypy.rpython.annlowlevel import llhelper # XXX: Also defined in object.h Py_LT = 0 @@ -39,7 +41,7 @@ func_init = rffi.cast(initproc, func) res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) if rffi.cast(lltype.Signed, res) == -1: - space.fromcache(State).check_and_raise_exception() + space.fromcache(State).check_and_raise_exception(always=True) return None def wrap_unaryfunc(space, w_self, w_args, func): @@ -81,6 +83,44 @@ if rffi.cast(lltype.Signed, res) == -1: space.fromcache(State).check_and_raise_exception(always=True) +def wrap_descr_get(space, w_self, w_args, func): + func_target = rffi.cast(descrgetfunc, func) + args_w = space.fixedview(w_args) + if len(args_w) == 1: + w_obj, = args_w + w_type = None + elif len(args_w) == 2: + w_obj, w_type = args_w + else: + raise operationerrfmt( + space.w_TypeError, + "expected 1 or 2 arguments, got %d", len(args_w)) + if w_obj is space.w_None: + w_obj = None + if w_type is space.w_None: + w_type = None + if w_obj is None and w_type is None: + raise OperationError( + space.w_TypeError, + space.wrap("__get__(None, None) is invalid")) + return generic_cpy_call(space, func_target, w_self, w_obj, w_type) + +def wrap_descr_set(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 2) + w_obj, w_value = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, w_value) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_descr_delete(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 1) + w_obj, = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, None) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + def wrap_call(space, w_self, w_args, func, w_kwds): func_target = rffi.cast(ternaryfunc, func) return generic_cpy_call(space, func_target, w_self, w_args, w_kwds) @@ -174,22 +214,64 @@ return space.call(w_self, w_args, w_kwds) @cpython_api([PyObject], PyObject, external=False) +def slot_tp_str(space, w_self): + return space.str(w_self) + + at cpython_api([PyObject], PyObject, external=False) def slot_nb_int(space, w_self): return space.int(w_self) - at cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1, external=False) -def slot_tp_setattro(space, w_self, w_name, w_value): - # XXX this is probably wrong when a subtype's tp_setattro - # delegates to PyType_Type.tp_setattro! - if w_value is not None: - space.setattr(w_self, w_name, w_value) +from pypy.rlib.nonconst import NonConstant + +SLOTS = {} + + at specialize.memo() +def get_slot_tp_function(space, typedef, name): + key = (typedef, name) + try: + return SLOTS[key] + except KeyError: + ret = build_slot_tp_function(space, typedef, name) + SLOTS[key] = ret + return ret + +def build_slot_tp_function(space, typedef, name): + w_type = space.gettypeobject(typedef) + + if name == 'tp_setattro': + setattr_fn = w_type.getdictvalue(space, '__setattr__') + delattr_fn = w_type.getdictvalue(space, '__delattr__') + if setattr_fn is None: + return + + @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, + error=-1, external=True) # XXX should not be exported + @func_renamer("cpyext_tp_setattro_%s" % (typedef.name,)) + def slot_tp_setattro(space, w_self, w_name, w_value): + if w_value is not None: + space.call_function(setattr_fn, w_self, w_name, w_value) + else: + space.call_function(delattr_fn, w_self, w_name) + return 0 + api_func = slot_tp_setattro.api_func else: - space.delattr(w_self, w_name) - return 0 + return + + return lambda: llhelper(api_func.functype, api_func._get_wrapper(space)) PyWrapperFlag_KEYWORDS = 1 -# adopted from typeobject.c +class TypeSlot: + def __init__(self, method_name, slot_name, function, wrapper1, wrapper2, doc): + self.method_name = method_name + self.slot_name = slot_name + self.slot_names = ("c_" + slot_name).split(".") + self.slot_func = function + self.wrapper_func = wrapper1 + self.wrapper_func_kwds = wrapper2 + self.doc = doc + +# adapted from typeobject.c def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS): if WRAPPER is None: wrapper = None @@ -201,23 +283,22 @@ wrapper = wrap_getattr function = globals().get(FUNCTION, None) - slotname = ("c_" + SLOT).split(".") assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func, w_kwds): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = None wrapper2 = wrapper else: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = wrapper wrapper2 = None - return (NAME, slotname, function, wrapper1, wrapper2, DOC) + return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC): return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0) @@ -470,7 +551,12 @@ for regex, repl in slotdef_replacements: slotdefs_str = re.sub(regex, repl, slotdefs_str) -slotdefs = unrolling_iterable(eval(slotdefs_str)) +slotdefs_for_tp_slots = unrolling_iterable( + [(x.method_name, x.slot_name, x.slot_names, x.slot_func) + for x in eval(slotdefs_str)]) +slotdefs_for_wrappers = unrolling_iterable( + [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) + for x in eval(slotdefs_str)]) if __name__ == "__main__": print slotdefs_str Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py Tue Jun 8 16:48:41 2010 @@ -180,9 +180,7 @@ the address in *string may differ from its input value. If the reallocation fails, the original string object at *string is deallocated, *string is set to NULL, a memory exception is set, and -1 is returned. - - This function used an int type for newsize. This might - require changes in your code for properly supporting 64-bit systems.""" + """ # XXX always create a new string so far py_str = rffi.cast(PyStringObject, ref[0]) if not py_str.c_buffer: Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubs.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubs.py Tue Jun 8 16:48:41 2010 @@ -23,7 +23,7 @@ _inittab = lltype.Void PyThreadState = lltype.Void PyInterpreterState = lltype.Void -PyOS_sighandler_t = lltype.Void +#PyOS_sighandler_t = lltype.Void Py_UNICODE = lltype.Void PyCompilerFlags = lltype.Void _node = lltype.Void @@ -574,62 +574,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_Check(space, ob): - """Return true if ob is of type PyDateTime_DateType or a subtype of - PyDateTime_DateType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_Check(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType or a subtype of - PyDateTime_DateTimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType. ob must not - be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_Check(space, ob): - """Return true if ob is of type PyDateTime_TimeType or a subtype of - PyDateTime_TimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_TimeType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_Check(space, ob): - """Return true if ob is of type PyDateTime_DeltaType or a subtype of - PyDateTime_DeltaType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DeltaType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyTZInfo_Check(space, ob): """Return true if ob is of type PyDateTime_TZInfoType or a subtype of PyDateTime_TZInfoType. ob must not be NULL. @@ -643,108 +587,6 @@ """ raise NotImplementedError - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): - """Return a datetime.date object with the specified year, month and day. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): - """Return a datetime.datetime object with the specified year, month, day, hour, - minute, second and microsecond. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): - """Return a datetime.timedelta object representing the given number of days, - seconds and microseconds. Normalization is performed so that the resulting - number of microseconds and seconds lie in the ranges documented for - datetime.timedelta objects. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_YEAR(space, o): - """Return the year, as a positive int. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_MONTH(space, o): - """Return the month, as an int from 1 through 12. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_DAY(space, o): - """Return the day, as an int from 1 through 31. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDateTime_FromTimestamp(space, args): - """Create and return a new datetime.datetime object given an argument tuple - suitable for passing to datetime.datetime.fromtimestamp(). - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDate_FromTimestamp(space, args): - """Create and return a new datetime.date object given an argument tuple - suitable for passing to datetime.date.fromtimestamp(). - """ - raise NotImplementedError - @cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject) def PyDescr_NewGetSet(space, type, getset): raise NotImplementedError @@ -2363,9 +2205,7 @@ @cpython_api([PyObject], PyObject) def PyObject_Dir(space, o): - """This is equivalent to the Python expression dir(o), returning a (possibly - empty) list of strings appropriate for the object argument, or NULL if there - was an error. If the argument is NULL, this is like the Python dir(), + """This is equivalent to the Python expression dir(o), returning a (possibly empty) list of strings appropriate for the object argument, or NULL if there was an error. If the argument is NULL, this is like the Python dir(), returning the names of the current locals; in this case, if no execution frame is active then NULL is returned but PyErr_Occurred() will return false.""" raise NotImplementedError @@ -2403,15 +2243,6 @@ func.""" raise NotImplementedError - at cpython_api([PyObject, Py_ssize_t], PyObject) -def PySequence_Repeat(space, o, count): - """Return the result of repeating sequence object o count times, or NULL on - failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject], PyObject) def PySequence_InPlaceConcat(space, o1, o2): """Return the concatenation of o1 and o2 on success, and NULL on failure. @@ -2474,12 +2305,6 @@ in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PySequence_List(space, o): - """Return a list object with the same contents as the arbitrary sequence o. The - returned list is guaranteed to be new.""" - raise NotImplementedError - @cpython_api([PyObject], PyObjectP, error=lltype.nullptr(PyObjectP.TO)) def PySequence_Fast_ITEMS(space, o): """Return the underlying array of PyObject pointers. Assumes that o was returned @@ -3142,13 +2967,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsUnicodeEscapeString(space, unicode): - """Encode a Unicode object using Unicode-Escape and return the result as Python - string object. Error handling is "strict". Return NULL if an exception was - raised by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject) def PyUnicode_DecodeRawUnicodeEscape(space, s, size, errors): """Create a Unicode object by decoding size bytes of the Raw-Unicode-Escape Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/foo.c ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/foo.c (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/foo.c Tue Jun 8 16:48:41 2010 @@ -483,6 +483,90 @@ 0 /*tp_weaklist*/ }; +PyObject * prop_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + if (obj == NULL) + obj = Py_None; + if (type == NULL) + type = Py_None; + + return PyTuple_Pack(3, self, obj, type); +} + +int prop_descr_set(PyObject *self, PyObject *obj, PyObject *value) +{ + int res; + if (value != NULL) { + PyObject *result = PyTuple_Pack(2, self, value); + res = PyObject_SetAttrString(obj, "y", result); + Py_DECREF(result); + } + else { + res = PyObject_SetAttrString(obj, "z", self); + } + return res; +} + + +PyTypeObject SimplePropertyType = { + PyObject_HEAD_INIT(NULL) + 0, + "foo.Property", + sizeof(PyObject), + 0, + 0, /*tp_dealloc*/ + 0, /*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*/ + + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + 0, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + prop_descr_get, /*tp_descr_get*/ + prop_descr_set, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + 0, /*tp_init*/ + 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ + 0, /*tp_new*/ + 0, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + /* Initialize this module. */ @@ -506,6 +590,8 @@ return; if (PyType_Ready(&InitErrType) < 0) return; + if (PyType_Ready(&SimplePropertyType) < 0) + return; m = Py_InitModule("foo", foo_functions); if (m == NULL) return; @@ -522,4 +608,6 @@ return; if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0) return; + if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0) + return; } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_datetime.py Tue Jun 8 16:48:41 2010 @@ -1,7 +1,99 @@ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.test.test_api import BaseApiTest +import datetime class TestDatetime(BaseApiTest): + def test_date(self, space, api): + w_date = api.PyDate_FromDate(2010, 06, 03) + assert space.unwrap(space.str(w_date)) == '2010-06-03' + + assert api.PyDate_Check(w_date) + assert api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date)])) == ( + 2010, 06, 03) + def test_time(self, space, api): w_time = api.PyTime_FromTime(23, 15, 40, 123456) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' + + assert api.PyTime_Check(w_time) + assert api.PyTime_CheckExact(w_time) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_TIME_GET_HOUR(w_time), + api.PyDateTime_TIME_GET_MINUTE(w_time), + api.PyDateTime_TIME_GET_SECOND(w_time), + api.PyDateTime_TIME_GET_MICROSECOND(w_time)])) == ( + 23, 15, 40, 123456) + + def test_datetime(self, space, api): + w_date = api.PyDateTime_FromDateAndTime( + 2010, 06, 03, 23, 15, 40, 123456) + assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456' + + assert api.PyDateTime_Check(w_date) + assert api.PyDateTime_CheckExact(w_date) + assert api.PyDate_Check(w_date) + assert not api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date), + api.PyDateTime_DATE_GET_HOUR(w_date), + api.PyDateTime_DATE_GET_MINUTE(w_date), + api.PyDateTime_DATE_GET_SECOND(w_date), + api.PyDateTime_DATE_GET_MICROSECOND(w_date)])) == ( + 2010, 06, 03, 23, 15, 40, 123456) + + def test_delta(self, space, api): + w_delta = space.appexec( + [space.wrap(3), space.wrap(15)], """(days, seconds): + from datetime import timedelta + return timedelta(days, seconds) + """) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + w_delta = api.PyDelta_FromDSU(10, 20, 30) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_DELTA_GET_DAYS(w_delta), + api.PyDateTime_DELTA_GET_SECONDS(w_delta), + api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta)])) == ( + 10, 20, 30) + + def test_fromtimestamp(self, space, api): + w_args = space.wrap((0,)) + w_date = api.PyDate_FromTimestamp(w_args) + date = datetime.date.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) + + w_args = space.wrap((0,)) + w_date = api.PyDateTime_FromTimestamp(w_args) + date = datetime.datetime.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) + +class AppTestDatetime(AppTestCpythonExtensionBase): + def test_CAPI(self): + module = self.import_extension('foo', [ + ("get_types", "METH_NOARGS", + """ + return PyTuple_Pack(4, + PyDateTimeAPI->DateType, + PyDateTimeAPI->DateTimeType, + PyDateTimeAPI->TimeType, + PyDateTimeAPI->DeltaType); + """), + ]) + import datetime + assert module.get_types() == (datetime.date, + datetime.datetime, + datetime.time, + datetime.timedelta) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_longobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_longobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_longobject.py Tue Jun 8 16:48:41 2010 @@ -76,7 +76,8 @@ """ return PyLong_FromUnsignedLong((unsigned long)-1); """)]) - assert module.from_unsignedlong() == (1<<32) - 1 + import sys + assert module.from_unsignedlong() == 2 * sys.maxint + 1 def test_fromlonglong(self): module = self.import_extension('foo', [ Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sequence.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sequence.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sequence.py Tue Jun 8 16:48:41 2010 @@ -8,7 +8,7 @@ def test_sequence(self, space, api): w_t = space.wrap((1, 2, 3, 4)) assert api.PySequence_Fast(w_t, "message") is w_t - w_l = space.wrap((1, 2, 3, 4)) + w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l assert space.int_w(api.PySequence_Fast_GET_ITEM(w_l, 1)) == 2 @@ -23,6 +23,19 @@ assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + w_seq = api.PySequence_List(w_set) + assert space.type(w_seq) is space.w_list + assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + + def test_repeat(self, space, api): + def test(seq, count): + w_seq = space.wrap(seq) + w_repeated = api.PySequence_Repeat(w_seq, count) + assert space.eq_w(w_repeated, space.wrap(seq * count)) + + test((1, 2, 3, 4), 3) + test([1, 2, 3, 4], 3) + def test_concat(self, space, api): w_t1 = space.wrap(range(4)) w_t2 = space.wrap(range(4, 8)) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sliceobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sliceobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_sliceobject.py Tue Jun 8 16:48:41 2010 @@ -43,3 +43,12 @@ ]) s = slice(10, 20, 30) assert module.clone(s) == s + + def test_nulls(self): + module = self.import_extension('foo', [ + ("nullslice", "METH_NOARGS", + """ + return PySlice_New(NULL, NULL, NULL); + """), + ]) + assert module.nullslice() == slice(None, None, None) Copied: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py (from r75197, pypy/trunk/pypy/module/cpyext/test/test_translate.py) ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_translate.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py Tue Jun 8 16:48:41 2010 @@ -24,7 +24,7 @@ return typedef.value api_func = slot_tp_function.api_func - return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) + return lambda: llhelper(api_func.functype, api_func._get_wrapper(space)) class Space: _cache = {} Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_typeobject.py Tue Jun 8 16:48:41 2010 @@ -192,6 +192,41 @@ assert d[cmpr] == 72 assert d[3] == 72 + def test_descriptor(self): + module = self.import_module("foo") + prop = module.Property() + class C(object): + x = prop + obj = C() + assert obj.x == (prop, obj, C) + assert C.x == (prop, None, C) + + obj.x = 2 + assert obj.y == (prop, 2) + del obj.x + assert obj.z == prop + + def test_tp_dict(self): + foo = self.import_module("foo") + module = self.import_extension('test', [ + ("read_tp_dict", "METH_O", + ''' + PyObject *method; + if (!args->ob_type->tp_dict) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + method = PyDict_GetItemString( + args->ob_type->tp_dict, "copy"); + Py_INCREF(method); + return method; + ''' + ) + ]) + obj = foo.new() + assert module.read_tp_dict(obj) == foo.fooType.copy + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): @@ -240,11 +275,17 @@ PyErr_SetString(PyExc_ValueError, "missing tp_setattro"); return NULL; } + if (args->ob_type->tp_setattro == + args->ob_type->tp_base->tp_setattro) + { + PyErr_SetString(PyExc_ValueError, "recursive tp_setattro"); + return NULL; + } Py_RETURN_TRUE; ''' ) ]) - assert module.test_type(None) + assert module.test_type(type(None)) def test_nb_int(self): module = self.import_extension('foo', [ @@ -283,3 +324,21 @@ def __call__(self, *args): return args assert module.tp_call(C(), ('x', 2)) == ('x', 2) + + def test_tp_str(self): + module = self.import_extension('foo', [ + ("tp_str", "METH_O", + ''' + if (!args->ob_type->tp_str) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + return args->ob_type->tp_str(args); + ''' + ) + ]) + class C: + def __str__(self): + return "text" + assert module.tp_str(C()) == "text" Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_unicodeobject.py Tue Jun 8 16:48:41 2010 @@ -49,7 +49,14 @@ space.newtuple([1, 2, 3]), None, None) self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString, space.wrap(''), None, None) + ascii = rffi.str2charp('ascii') + replace = rffi.str2charp('replace') + encoded = api.PyUnicode_AsEncodedString(space.wrap(u'sp?m'), + ascii, replace) + assert space.unwrap(encoded) == 'sp?m' rffi.free_charp(utf_8) + rffi.free_charp(replace) + rffi.free_charp(ascii) buf = rffi.unicode2wcharp(u"12345") api.PyUnicode_AsWideChar(space.wrap(u'longword'), buf, 5) @@ -143,3 +150,14 @@ rffi.free_wcharp(wbuf) assert space.type(w_str) is space.w_str assert space.str_w(w_str) == "abc?" + + def test_escape(self, space, api): + def test(ustr): + w_ustr = space.wrap(ustr.decode('Unicode-Escape')) + result = api.PyUnicode_AsUnicodeEscapeString(w_ustr) + assert space.eq_w(space.wrap(ustr), result) + + test('\\u674f\\u7f8e') + test('\\u0105\\u0107\\u017c\\u017a') + test('El Ni\\xf1o') + Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py Tue Jun 8 16:48:41 2010 @@ -25,7 +25,8 @@ from pypy.module.cpyext.typeobjectdefs import ( PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, PyNumberMethods) -from pypy.module.cpyext.slotdefs import slotdefs +from pypy.module.cpyext.slotdefs import ( + slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function) from pypy.interpreter.error import OperationError from pypy.rlib.rstring import rsplit from pypy.rlib.objectmodel import specialize @@ -102,47 +103,59 @@ def update_all_slots(space, w_type, pto): # XXX fill slots in pto - for method_name, slot_name, slot_func, _, _, _ in slotdefs: + + typedef = w_type.instancetypedef + for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: w_descr = w_type.lookup(method_name) if w_descr is None: # XXX special case iternext continue - if slot_func is None: + + slot_func_helper = None + + if slot_func is None and typedef is not None: + get_slot = get_slot_tp_function(space, typedef, slot_name) + if get_slot: + slot_func_helper = get_slot() + elif slot_func: + slot_func_helper = slot_func.api_func.get_llpointer_maker(space)() + + if slot_func_helper is None: if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: os.write(2, method_name + " defined by the type but no slot function defined!\n") continue - slot_func_helper = slot_func.api_func.get_llpointer_maker(space)() + # XXX special case wrapper-functions and use a "specific" slot func - if len(slot_name) == 1: - setattr(pto, slot_name[0], slot_func_helper) + if len(slot_names) == 1: + setattr(pto, slot_names[0], slot_func_helper) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: - if slot_name[0] == 'c_tp_as_number': + if slot_names[0] == 'c_tp_as_number': STRUCT_TYPE = PyNumberMethods else: raise AssertionError( - "Structure not allocated: %s" % (slot_name[0],)) + "Structure not allocated: %s" % (slot_names[0],)) struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) - setattr(pto, slot_name[0], struct) + setattr(pto, slot_names[0], struct) - setattr(struct, slot_name[1], slot_func_helper) + setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): # XXX support PyObject_HashNotImplemented - for method_name, slot_name, _, wrapper_func, wrapper_func_kwds, doc in slotdefs: + for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue - if len(slot_name) == 1: - func = getattr(pto, slot_name[0]) + if len(slot_names) == 1: + func = getattr(pto, slot_names[0]) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: continue - func = getattr(struct, slot_name[1]) + func = getattr(struct, slot_names[1]) func_voidp = rffi.cast(rffi.VOIDP_real, func) if not func: continue @@ -359,12 +372,13 @@ @cpython_api([PyObject], lltype.Void, external=False) def type_dealloc(space, obj): + from pypy.module.cpyext.object import PyObject_dealloc obj_pto = rffi.cast(PyTypeObjectPtr, obj) - type_pto = obj.c_ob_type base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base) Py_DecRef(space, obj_pto.c_tp_bases) Py_DecRef(space, obj_pto.c_tp_mro) Py_DecRef(space, obj_pto.c_tp_cache) # let's do it like cpython + Py_DecRef(space, obj_pto.c_tp_dict) if obj_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: if obj_pto.c_tp_as_buffer: lltype.free(obj_pto.c_tp_as_buffer, flavor='raw') @@ -372,11 +386,7 @@ lltype.free(obj_pto.c_tp_as_number, flavor='raw') Py_DecRef(space, base_pyo) rffi.free_charp(obj_pto.c_tp_name) - obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto) - generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp) - if type_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: - pto = rffi.cast(PyObject, type_pto) - Py_DecRef(space, pto) + PyObject_dealloc(space, obj) def type_attach(space, py_obj, w_type): @@ -488,6 +498,8 @@ # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free + if not pto.c_tp_setattro: + pto.c_tp_setattro = base.c_tp_setattro finally: Py_DecRef(space, base_pyo) @@ -526,8 +538,6 @@ """ Sets up tp_bases, necessary before creating the interpreter type. """ - pto.c_tp_dict = lltype.nullptr(PyObject.TO) # not supported - base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: @@ -552,6 +562,16 @@ for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): inherit_slots(space, pto, w_base) + if not pto.c_tp_setattro: + from pypy.module.cpyext.object import PyObject_GenericSetAttr + pto.c_tp_setattro = llhelper( + PyObject_GenericSetAttr.api_func.functype, + PyObject_GenericSetAttr.api_func._get_wrapper(space)) + + if w_obj.is_cpytype(): + Py_DecRef(space, pto.c_tp_dict) + pto.c_tp_dict = make_ref(space, w_obj.getdict()) + @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py Tue Jun 8 16:48:41 2010 @@ -105,10 +105,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyUnicode_GET_SIZE(space, w_obj): """Return the size of the object. o has to be a PyUnicodeObject (not - checked). - - This function returned an int type. This might require changes - in your code for properly supporting 64-bit systems.""" + checked).""" assert isinstance(w_obj, unicodeobject.W_UnicodeObject) return space.int_w(space.len(w_obj)) @@ -190,7 +187,7 @@ return 0 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject) -def PyUnicode_AsEncodedString(space, w_unicode, encoding, errors): +def PyUnicode_AsEncodedString(space, w_unicode, llencoding, llerrors): """Encode a Unicode object and return the result as Python string object. encoding and errors have the same meaning as the parameters of the same name in the Unicode encode() method. The codec to be used is looked up using @@ -199,12 +196,22 @@ if not PyUnicode_Check(space, w_unicode): PyErr_BadArgument(space) - w_encoding = w_errors = None - if encoding: - w_encoding = rffi.charp2str(encoding) - if errors: - w_errors = rffi.charp2str(encoding) - return unicodetype.encode_object(space, w_unicode, w_encoding, w_errors) + encoding = errors = None + if llencoding: + encoding = rffi.charp2str(llencoding) + if llerrors: + errors = rffi.charp2str(llerrors) + return unicodetype.encode_object(space, w_unicode, encoding, errors) + + at cpython_api([PyObject], PyObject) +def PyUnicode_AsUnicodeEscapeString(space, w_unicode): + """Encode a Unicode object using Unicode-Escape and return the result as Python + string object. Error handling is "strict". Return NULL if an exception was + raised by the codec.""" + if not PyUnicode_Check(space, w_unicode): + PyErr_BadArgument(space) + + return unicodetype.encode_object(space, w_unicode, 'unicode-escape', 'strict') @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject) def PyUnicode_FromUnicode(space, wchar_p, length): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/imp/importing.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/imp/importing.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/imp/importing.py Tue Jun 8 16:48:41 2010 @@ -145,7 +145,7 @@ msg = "Attempted relative import in non-package" raise OperationError(space.w_ValueError, w(msg)) w_mod = absolute_import_try(space, modulename, 0, fromlist_w) - if w_mod is None and not space.is_w(w_mod, space.w_None): + if w_mod is None or space.is_w(w_mod, space.w_None): w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0) if rel_modulename is not None: space.setitem(space.sys.get('modules'), w(rel_modulename), space.w_None) @@ -178,13 +178,11 @@ else: level = 0 first = None - while last_dot != -1: - assert last_dot >= 0 # bah + while last_dot >= 0: last_dot = modulename.find('.', last_dot + 1) - if last_dot == -1: + if last_dot < 0: w_mod = check_sys_modules_w(space, modulename) else: - assert last_dot >= 0 w_mod = check_sys_modules_w(space, modulename[:last_dot]) if w_mod is None or space.is_w(w_mod, space.w_None): return None Modified: pypy/branch/cpyext-init-cleanup/pypy/module/imp/test/test_import.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/imp/test/test_import.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/imp/test/test_import.py Tue Jun 8 16:48:41 2010 @@ -457,6 +457,16 @@ def test_reload_infinite(self): import infinite_reload + def test_explicitly_missing(self): + import sys + sys.modules['foobarbazmod'] = None + try: + import foobarbazmod + assert False, "should have failed, got instead %r" % ( + foobarbazmod,) + except ImportError: + pass + def _getlong(data): x = marshal.dumps(data) return x[-4:] Modified: pypy/branch/cpyext-init-cleanup/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/sys/__init__.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/sys/__init__.py Tue Jun 8 16:48:41 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.interpreter.error import OperationError +from pypy.rlib.objectmodel import we_are_translated import sys class Module(MixedModule): @@ -92,8 +93,12 @@ self.space.setitem(w_modules, w_name, w_module) def startup(self, space): - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) + if space.config.translating and not we_are_translated(): + # don't get the filesystemencoding at translation time + assert self.filesystemencoding is None + else: + from pypy.module.sys.interp_encoding import _getfilesystemencoding + self.filesystemencoding = _getfilesystemencoding(space) def getmodule(self, name): space = self.space Modified: pypy/branch/cpyext-init-cleanup/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/sys/interp_encoding.py Tue Jun 8 16:48:41 2010 @@ -1,5 +1,6 @@ import sys from pypy.rlib import rlocale +from pypy.rlib.objectmodel import we_are_translated def getdefaultencoding(space): """Return the current default string encoding used by the Unicode @@ -18,6 +19,8 @@ space.sys.defaultencoding = encoding def get_w_default_encoder(space): + assert not (space.config.translating and not we_are_translated()), \ + "get_w_default_encoder() should not be called during translation" w_encoding = space.wrap(space.sys.defaultencoding) mod = space.getbuiltinmodule("_codecs") w_lookup = space.getattr(mod, space.wrap("lookup")) @@ -40,6 +43,8 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: + if loc_codeset == 'ANSI_X3.4-1968': + loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), Modified: pypy/branch/cpyext-init-cleanup/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/objspace/std/formatting.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/objspace/std/formatting.py Tue Jun 8 16:48:41 2010 @@ -474,12 +474,6 @@ [_name[-1] for _name in dir(StringFormatter) if len(_name) == 5 and _name.startswith('fmt_')]) -def is_list_of_chars_or_unichars(ann, bk): - from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint - if not isinstance(ann.listdef.listitem.s_value, - (SomeChar, SomeUnicodeCodePoint)): - raise TypeError("Formatter should return as a result a list of chars or unichars, otherwise we miss important optimization") - def format(space, w_fmt, values_w, w_valuedict=None, do_unicode=False): "Entry point" if not do_unicode: Modified: pypy/branch/cpyext-init-cleanup/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/objspace/std/test/test_stringformat.py Tue Jun 8 16:48:41 2010 @@ -125,6 +125,15 @@ assert '27' == '%.2o' % n assert '027' == '%#.2o' % n + def test_format_long(self): + l = 4800000000L + assert '%d' % l == '4800000000' + # + class SubLong(long): + pass + sl = SubLong(l) + assert '%d' % sl == '4800000000' + def test_format_list(self): l = [1,2] assert '<[1, 2]>' == '<%s>' % l Modified: pypy/branch/cpyext-init-cleanup/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/objspace/std/unicodetype.py Tue Jun 8 16:48:41 2010 @@ -3,6 +3,8 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii,\ + unicode_encode_utf_8, unicode_encode_ascii from sys import maxint @@ -183,13 +185,27 @@ return encoding, errors def encode_object(space, w_object, encoding, errors): - # XXX write down shortcuts for performance for common encodings, - # just like CPython if encoding is None: # Get the encoder functions as a wrapped object. # This lookup is cached. w_encoder = space.sys.get_w_default_encoder() else: + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_ascii(u, len(u), None)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + return space.wrap(unicode_encode_utf_8(u, len(u), None)) + except UnicodeEncodeError, uee: + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([ + space.wrap(uee.encoding), + space.wrap(uee.object), + space.wrap(uee.start), + space.wrap(uee.end), + space.wrap(uee.reason)])) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -205,9 +221,23 @@ return w_retval def decode_object(space, w_obj, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") if encoding is None: encoding = getdefaultencoding(space) + if errors is None or errors == 'strict': + try: + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_ascii(s, len(s), None)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + return space.wrap(str_decode_utf_8(s, len(s), None)[0]) + except UnicodeDecodeError, ude: + raise OperationError(space.w_UnicodeDecodeError, space.newtuple( + [space.wrap(ude.encoding), space.wrap(ude.object), + space.wrap(ude.start), space.wrap(ude.end), + space.wrap(ude.reason)])) + w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: w_retval = space.call_function(w_decode, w_obj, space.wrap(encoding)) Modified: pypy/branch/cpyext-init-cleanup/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rlib/rarithmetic.py Tue Jun 8 16:48:41 2010 @@ -178,12 +178,6 @@ else: return super(base_int, klass).__new__(klass, val) - def __int__(self): - if self < LONG_TEST: - return long.__int__(self) - else: - return intmask(self) - def __add__(self, other): x = long(self) y = long(other) Modified: pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rarithmetic.py Tue Jun 8 16:48:41 2010 @@ -114,7 +114,10 @@ #self.binary_test(lambda x, y: pow(x, y, 42), (2, 3, 5, 1000)) def test_back_to_int(self): - assert int(r_uint(-1)) == -1 + #assert int(r_uint(-1)) == -1 + # ^^^ that looks wrong IMHO: int(x) should not by itself return + # an integer that has a different value than x, especially + # if x is a subclass of long. assert int(r_uint(1)) == 1 def unary_test(self, f): Modified: pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rlocale.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rlocale.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rlib/test/test_rlocale.py Tue Jun 8 16:48:41 2010 @@ -14,7 +14,8 @@ py.test.skip("polish locale unsupported") def teardown_class(cls): - setlocale(LC_ALL, cls.oldlocale) + if hasattr(cls, "oldlocale"): + setlocale(LC_ALL, cls.oldlocale) def test_setlocale_worked(self): assert u"??".isupper() Modified: pypy/branch/cpyext-init-cleanup/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rpython/lltypesystem/rstr.py Tue Jun 8 16:48:41 2010 @@ -18,6 +18,7 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -296,7 +297,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError + raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' Modified: pypy/branch/cpyext-init-cleanup/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rpython/rbuiltin.py Tue Jun 8 16:48:41 2010 @@ -270,6 +270,37 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) +def rtype_UnicodeDecodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeDecodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + TPS = [hop.args_r[0], r_str, r_str, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + +def rtype_UnicodeEncodeError_init(hop): + if hop.nb_args != 6: + raise TypeError("UnicodeEncodeError() should be called with 5 " + "arguments") + r_self = hop.args_r[0] + r_str = hop.rtyper.type_system.rstr.string_repr + r_unicode = hop.rtyper.type_system.rstr.unicode_repr + TPS = [hop.args_r[0], r_str, r_unicode, lltype.Signed, lltype.Signed, + r_str] + v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) + r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) + r_self.setfield(v_self, 'object', v_obj, hop.llops) + r_self.setfield(v_self, 'start', v_start, hop.llops) + r_self.setfield(v_self, 'end', v_end, hop.llops) + r_self.setfield(v_self, 'reason', v_msg, hop.llops) + def rtype_WindowsError__init__(hop): if hop.nb_args == 2: raise TyperError("WindowsError() should not be called with " @@ -329,6 +360,8 @@ BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( rtype_OSError__init__) +BUILTIN_TYPER[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = rtype_UnicodeDecodeError_init +BUILTIN_TYPER[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = rtype_UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/cpyext-init-cleanup/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/rpython/test/test_rbuiltin.py Tue Jun 8 16:48:41 2010 @@ -496,6 +496,35 @@ res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy()) assert res == 123 + def test_unicode_errors(self): + def f(): + try: + raise UnicodeDecodeError("xx", "x", 0, 1, "reason") + except UnicodeDecodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == "x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + + def f(): + try: + raise UnicodeEncodeError("xx", u"x", 0, 1, "reason") + except UnicodeEncodeError, ude: + assert ude.start == 0 + assert ude.encoding == "xx" + assert ude.object == u"x" + assert ude.start == 0 + assert ude.reason == "reason" + return ude.end + + res = self.interpret(f, []) + assert res == f() + class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): Modified: pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/appsupport.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/appsupport.py Tue Jun 8 16:48:41 2010 @@ -86,11 +86,18 @@ if debug_excs: self._excinfo = debug_excs[0] + def __repr__(self): + return "" % self.operr.errorstr(self.space) + def exconly(self, tryshort=True): return '(application-level) ' + self.operr.errorstr(self.space) def errisinstance(self, exc): clsname = exc.__name__ + # we can only check for builtin exceptions + # as there is no canonical applevel one for custom interplevel ones + if exc.__module__ != "exceptions": + return False try: w_exc = getattr(self.space, 'w_' + clsname) except KeyboardInterrupt: Modified: pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/test/test_appsupport.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/test/test_appsupport.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/tool/pytest/test/test_appsupport.py Tue Jun 8 16:48:41 2010 @@ -113,6 +113,19 @@ "*E*application-level*NameError*x*not defined", ]) +def test_applevel_raise_keyerror(testdir): + setpypyconftest(testdir) + p = testdir.makepyfile(""" + def app_test_raises(): + raise KeyError(42) + pass + """) + result = testdir.runpytest(p, "-s") + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "*E*application-level*KeyError*42*", + ]) + def app_test_raises(): info = raises(TypeError, id) assert info.type is TypeError Modified: pypy/branch/cpyext-init-cleanup/pypy/tool/sourcetools.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/tool/sourcetools.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/tool/sourcetools.py Tue Jun 8 16:48:41 2010 @@ -227,6 +227,12 @@ f.func_dict.update(func.func_dict) return f +def func_renamer(newname): + """A function decorator which changes the name of a function.""" + def decorate(func): + return func_with_new_name(func, newname) + return decorate + PY_IDENTIFIER = ''.join([(('0' <= chr(i) <= '9' or 'a' <= chr(i) <= 'z' or 'A' <= chr(i) <= 'Z') and chr(i) or '_') Modified: pypy/branch/cpyext-init-cleanup/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/translator/c/test/test_standalone.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/translator/c/test/test_standalone.py Tue Jun 8 16:48:41 2010 @@ -210,6 +210,7 @@ filename = str(udir.join('test_standalone_largefile')) r4800000000 = r_longlong(4800000000L) def entry_point(argv): + assert str(r4800000000 + len(argv)) == '4800000003' fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644) os.lseek(fd, r4800000000, 0) newpos = os.lseek(fd, 0, 1) From afa at codespeak.net Tue Jun 8 17:19:00 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 17:19:00 +0200 (CEST) Subject: [pypy-svn] r75199 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608151900.334D6282BDB@codespeak.net> Author: afa Date: Tue Jun 8 17:18:58 2010 New Revision: 75199 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: start to refactor the GLOBALS dict Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 17:18:58 2010 @@ -115,6 +115,14 @@ for name in ("pypy_decl.h", "pypy_macros.h"): udir.join(name).copy(interfaces_dir / name) +class BaseGlobalObject: + """Base class for all objects (pointers and structures)""" + + @classmethod + def declare(cls, *args, **kwargs): + obj = cls(*args, **kwargs) + GLOBALS[obj.name] = obj + _NOT_SPECIFIED = object() CANNOT_FAIL = object() @@ -329,23 +337,48 @@ 'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer', ] TYPES = {} -GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur - '_Py_NoneStruct#': ('PyObject*', 'space.w_None'), - '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), - '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), - '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), - 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'), - } +GLOBALS = {} FORWARD_DECLS = [] INIT_FUNCTIONS = [] BOOTSTRAP_FUNCTIONS = [] +class GlobalStaticPyObject(BaseGlobalObject): + def __init__(self, name, expr): + self.name = name + '#' + self.type = 'PyObject*' + self.expr = expr + +class GlobalStructurePointer(BaseGlobalObject): + def __init__(self, name, type, expr): + self.name = name + self.type = type + self.expr = expr + +class GlobalExceptionPointer(BaseGlobalObject): + def __init__(self, exc_name): + self.name = 'PyExc_' + exc_name + self.type = 'PyTypeObject*' + self.expr = ('space.gettypeobject(interp_exceptions.W_%s.typedef)' + % (exc_name,)) + +class GlobalTypeObject(BaseGlobalObject): + def __init__(self, name, expr): + self.name = 'Py%s_Type#' % (name,) + self.type = 'PyTypeObject*' + self.expr = expr + +GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') +GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') +GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') +GlobalStaticPyObject.declare('_Py_NotImplementedStruct', + 'space.w_NotImplemented') +GlobalStructurePointer.declare('PyDateTimeAPI', 'PyDateTime_CAPI*', + 'cpyext.datetime.build_datetime_api(space)') + def build_exported_objects(): # Standard exceptions for exc_name in exceptions.Module.interpleveldefs.keys(): - GLOBALS['PyExc_' + exc_name] = ( - 'PyTypeObject*', - 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, )) + GlobalExceptionPointer.declare(exc_name) # Common types with their own struct for cpyname, pypyexpr in { @@ -371,7 +404,7 @@ 'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)', 'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)', }.items(): - GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr) + GlobalTypeObject.declare(cpyname, pypyexpr) for cpyname in 'Method List Int Long Dict Tuple Class'.split(): FORWARD_DECLS.append('typedef struct { PyObject_HEAD } ' @@ -614,15 +647,15 @@ functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] - for name, (typ, expr) in GLOBALS.iteritems(): - if "#" in name: + for obj in GLOBALS.values(): + if "#" in obj.name: continue - if typ == 'PyDateTime_CAPI*': - global_objects.append('%s _%s;' % (typ, name)) - elif name.startswith('PyExc_'): - global_objects.append('%s _%s;' % (typ[:-1], name)) + if obj.type == 'PyDateTime_CAPI*': + global_objects.append('%s _%s;' % (obj.type, obj.name)) + elif obj.name.startswith('PyExc_'): + global_objects.append('%s _%s;' % (obj.type[:-1], obj.name)) else: - global_objects.append('%s %s = NULL;' % (typ, name)) + global_objects.append('%s %s = NULL;' % (obj.typ, obj.name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -644,13 +677,14 @@ bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) # populate static data - for name, (typ, expr) in GLOBALS.iteritems(): + for obj in GLOBALS.values(): from pypy.module import cpyext - w_obj = eval(expr) - if name.endswith('#'): - name = name[:-1] + w_obj = eval(obj.expr) + if obj.name.endswith('#'): + name = obj.name[:-1] isptr = False else: + name = obj.name isptr = True if name.startswith('PyExc_'): isptr = False @@ -660,15 +694,15 @@ name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) - if typ == 'PyObject*': + if obj.type == 'PyObject*': value = make_ref(space, w_obj) - elif typ == 'PyDateTime_CAPI*': + elif obj.type == 'PyDateTime_CAPI*': value = w_obj else: assert False, "Unknown static pointer: %s %s" % (typ, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value - elif typ in ('PyObject*', 'PyTypeObject*'): + elif obj.type in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) @@ -764,13 +798,15 @@ body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) - for name, (typ, expr) in GLOBALS.iteritems(): - if name.endswith('#'): + for obj in GLOBALS.values(): + name = obj.name + type = obj.type + if obj.name.endswith('#'): name = name.replace("#", "") - typ = typ.replace("*", "") + type = type.replace("*", "") elif name.startswith('PyExc_'): - typ = 'PyObject*' - pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) + type = 'PyObject*' + pypy_decls.append('PyAPI_DATA(%s) %s;' % (type, name)) pypy_decls.append("#ifdef __cplusplus") pypy_decls.append("}") @@ -802,15 +838,15 @@ # Generate definitions for global structures struct_file = udir.join('pypy_structs.c') structs = ["#include "] - for name, (typ, expr) in GLOBALS.iteritems(): - if name.endswith('#'): - structs.append('%s %s;' % (typ[:-1], name[:-1])) - elif name.startswith('PyExc_'): - structs.append('extern PyTypeObject _%s;' % (name,)) - structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) - elif typ == 'PyDateTime_CAPI*': - structs.append('extern %s _%s;' % (typ[:-1], name)) - structs.append('%s %s = &_%s;' % (typ, name, name)) + for obj in GLOBALS.values(): + if obj.name.endswith('#'): + structs.append('%s %s;' % (obj.type[:-1], obj.name[:-1])) + elif obj.name.startswith('PyExc_'): + structs.append('extern PyTypeObject _%s;' % (obj.name,)) + structs.append('PyObject* %s = (PyObject*)&_%s;' % (obj.name, obj.name)) + elif obj.type == 'PyDateTime_CAPI*': + structs.append('extern %s _%s;' % (obj.type[:-1], obj.name)) + structs.append('%s %s = &_%s;' % (obj.type, obj.name, obj.name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -853,20 +889,20 @@ run_bootstrap_functions(space) # populate static data - for name, (typ, expr) in GLOBALS.iteritems(): - name = name.replace("#", "") + for obj in GLOBALS.values(): + name = obj.name.replace("#", "") if name.startswith('PyExc_'): name = '_' + name from pypy.module import cpyext - w_obj = eval(expr) - if typ in ('PyObject*', 'PyTypeObject*'): + w_obj = eval(obj.expr) + if obj.type in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) - elif typ == 'PyDateTime_CAPI*': + elif obj.type == 'PyDateTime_CAPI*': struct_ptr = w_obj name = '_' + name else: - assert False, "Unknown static data: %s %s" % (typ, name) - struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj + assert False, "Unknown static data: %s %s" % (obj.type, name) + struct = rffi.cast(get_structtype_for_ctype(obj.type), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) From benjamin at codespeak.net Tue Jun 8 17:20:32 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 8 Jun 2010 17:20:32 +0200 (CEST) Subject: [pypy-svn] r75200 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100608152032.86C5C282BDB@codespeak.net> Author: benjamin Date: Tue Jun 8 17:20:31 2010 New Revision: 75200 Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Log: add support for the thousands separator Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 8 17:20:31 2010 @@ -3,7 +3,7 @@ import string from pypy.interpreter.error import OperationError -from pypy.rlib import rstring, runicode +from pypy.rlib import rstring, runicode, rlocale from pypy.rlib.objectmodel import specialize @@ -411,16 +411,11 @@ def _get_locale(self, locale_kind): space = self.space if locale_kind == CURRENT_LOCALE: - _locale = space.getbuiltnmodule("_locale") - w_lconv = space.call_method(_locale, "localeconv") - w = space.wrap - dec = space.str_w(space.getitem(w_lconv, w("decimal_point"))) - thousands = space.str_w(space.getitem(w_lconv, w("thousands_sep"))) - grouping = space.str_w(space.getitem(w_lconv, w("grouping"))) + dec, thousands, grouping = rlocale.numeric_formatting() elif locale_kind == DEFAULT_LOCALE: dec = "." thousands = "," - grouping = "\3" + grouping = "\3\0" elif locale_kind == NO_LOCALE: dec = "." thousands = "" @@ -434,7 +429,7 @@ self._loc_grouping = grouping def _calc_num_width(self, n_prefix, sign_char, to_number, n_number, - n_remainder, has_dec): + n_remainder, has_dec, digits): spec = NumberSpec() spec.n_digits = n_number - n_remainder - has_dec spec.n_prefix = n_prefix @@ -443,6 +438,7 @@ spec.n_remainder = n_remainder spec.n_spadding = 0 spec.n_rpadding = 0 + spec.n_min_width = 0 spec.sign = "\0" spec.n_sign = 0 sign = self._sign @@ -459,7 +455,12 @@ spec.n_remainder) # Not padding or digits if self._fill_char == "0" and self._align == "=": spec.n_min_width = self._width - extra_length - n_padding = self._width - (extra_length + spec.n_digits) + if self._loc_thousands: + self._group_digits(spec, digits) + n_grouped_digits = len(self._grouped_digits) + else: + n_grouped_digits = spec.n_digits + n_padding = self._width - (extra_length + n_grouped_digits) if n_padding > 0: align = self._align if align == "<": @@ -475,6 +476,55 @@ raise AssertionError("shouldn't reach") return spec + def _fill_digits(self, buf, digits, d_state, n_chars, n_zeros, + thousands_sep): + if thousands_sep: + buf.extend(thousands_sep) + for i in range(d_state - 1, d_state - n_chars - 1, -1): + buf.append(digits[i]) + buf.extend(digits[d_state:d_state - n_chars]) + + def _group_digits(self, spec, digits): + buf = [] + grouping = self._loc_grouping + min_width = spec.n_min_width + i = 0 + count = 0 + left = spec.n_digits + n_ts = len(self._loc_thousands) + need_separator = False + done = False + groupings = len(grouping) + while True: + group = ord(grouping[i]) + if group > 0: + if group == 256: + break + i += 1 + previous = group + else: + group = previous + final_grouping = min(group, max(group, min_width, 1)) + n_zeros = max(0, final_grouping - left) + n_chars = max(0, min(left, final_grouping)) + ts = self._loc_thousands if need_separator else None + self._fill_digits(buf, digits, left, n_chars, n_zeros, ts) + need_separator = True + left -= n_chars + min_width -= 1 + if left <= 0 and min_width <= 0: + done = True + break + min_width -= n_ts + if not done: + group = max(max(left, min_width), 1) + n_zeros = max(0, group - left) + n_chars = max(0, min(left, group)) + ts = thousands_sep if need_separator else None + self._fill_digits(buf, digits, left, n_chars, n_zeros, ts) + buf.reverse() + self._grouped_digits = self.empty.join(buf) + def _upcase_string(self, s): buf = [] for c in s: @@ -500,7 +550,10 @@ if spec.n_spadding: out.append_multiple_char(fill_char, spec.n_spadding) if spec.n_digits != 0: - num = num[to_digits:] + if self._loc_thousands: + num = self._grouped_digits + else: + num = num[to_digits:] if upper: num = self._upcase_string(num) out.append(num) @@ -564,8 +617,15 @@ n_digits = len(result) - skip_leading n_remainder = 0 to_numeric = skip_leading + if tp == "n": + locale_kind = CURRENT_LOCALE + elif self._thousands_sep: + locale_kind = DEFAULT_LOCALE + else: + locale_kind = NO_LOCALE + self._get_locale(locale_kind) spec = self._calc_num_width(n_prefix, sign_char, to_numeric, n_digits, - n_remainder, False) + n_remainder, False, result) fill = " " if self._fill_char == "\0" else self._fill_char upper = self._type == "X" return self._fill_number(spec, result, to_numeric, n_digits, to_prefix, Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Tue Jun 8 17:20:31 2010 @@ -186,6 +186,13 @@ assert format(self.i(6), "-") == "6" assert format(self.i(6), "+") == "+6" + def test_thousands_separator(self): + assert format(self.i(123), ",") == "123" + assert format(self.i(12345), ",") == "12,345" + assert format(self.i(123456789), ",") == "123,456,789" + assert format(self.i(12345), "7,") == " 12,345" + assert format(self.i(12345), "<7,") == "12,345 " + class AppTestIntFormatting(BaseIntegralFormattingTest): From benjamin at codespeak.net Tue Jun 8 17:49:23 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 8 Jun 2010 17:49:23 +0200 (CEST) Subject: [pypy-svn] r75201 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100608154923.E0084282BDE@codespeak.net> Author: benjamin Date: Tue Jun 8 17:49:22 2010 New Revision: 75201 Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Log: catch integer overflows in format specifiers Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 8 17:49:22 2010 @@ -3,10 +3,32 @@ import string from pypy.interpreter.error import OperationError -from pypy.rlib import rstring, runicode, rlocale +from pypy.rlib import rstring, runicode, rlocale, rarithmetic from pypy.rlib.objectmodel import specialize + at specialize.argtype(1) +def _parse_int(space, s, start, end): + """Parse a number and check for overflows""" + result = 0 + i = start + while i < end: + c = ord(s[i]) + if ord("0") <= c <= ord("9"): + try: + result = rarithmetic.ovfcheck(result * 10) + except OverflowError: + msg = "too many decimal digits in format string" + raise OperationError(space.w_ValueError, space.wrap(msg)) + result += c - ord("0") + else: + break + i += 1 + if i == start: + result = -1 + return result, i + + # Auto number state ANS_INIT = 1 ANS_AUTO = 2 @@ -121,12 +143,11 @@ if c == "[" or c == ".": break i += 1 - arg_ref = name[:i] - try: - index = int(arg_ref) - except ValueError: - index = -1 empty = not i + if empty: + index = -1 + else: + index = _parse_int(self.space, name, 0, i)[0] use_numeric = empty or index != -1 if self.auto_numbering_state == ANS_INIT and use_numeric: if empty: @@ -147,10 +168,11 @@ index = self.auto_numbering self.auto_numbering += 1 if index == -1: + arg_key = name[:i] try: - w_arg = self.kwargs[arg_ref] + w_arg = self.kwargs[arg_key] except KeyError: - raise OperationError(space.w_KeyError, space.wrap(arg_ref)) + raise OperationError(space.w_KeyError, space.wrap(arg_key)) else: try: w_arg = self.args[index] @@ -184,14 +206,12 @@ if not got_bracket: raise OperationError(space.w_ValueError, space.wrap("Missing ']'")) - item = name[start:i] - i += 1 # Skip "]" - try: - index = int(item) - except ValueError: - w_item = space.wrap(item) - else: + index, reached = _parse_int(self.space, name, start, i) + if index != -1 and reached == i: w_item = space.wrap(index) + else: + w_item = space.wrap(name[start:i]) + i += 1 # Skip "]" w_obj = space.getitem(w_obj, w_item) else: msg = "Only '[' and '.' may follow ']'" @@ -270,16 +290,6 @@ c == "+" or c == "-") - def _get_integer(self, spec, i, length): - start_width = i - while i < length: - char_index = ord(spec[i]) - if char_index < ord("0") or ord("9") < char_index: - break - i += 1 - num = int(spec[start_width:i]) if start_width != i else -1 - return num, i - def _parse_spec(self, default_type, default_align): space = self.space self._fill_char = "\0" @@ -315,13 +325,14 @@ if not got_align: self._align = "=" i += 1 - self._width, i = self._get_integer(spec, i, length) + start_i = i + self._width, i = _parse_int(self.space, spec, i, length) if length - i and spec[i] == ",": self._thousands_sep = True i += 1 if length - i and spec[i] == ".": i += 1 - self._precision, i = self._get_integer(spec, i, length) + self._precision, i = _parse_int(self.space, spec, i, length) if self._precision == -1: raise OperationError(space.w_ValueError, space.wrap("no precision given")) Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Tue Jun 8 17:49:22 2010 @@ -32,6 +32,8 @@ def test_positional_args(self): assert self.s("{1}{0}").format(2, 3) == self.s("32") raises(IndexError, self.s("{2}").format, 2) + big = self.s("{123476028570192873049182730984172039840712934}") + raises(ValueError, big.format) def test_kwargs(self): assert self.s("{what}").format(what=42) == self.s("42") @@ -45,6 +47,8 @@ def test_index(self): seq = (1, 42) assert self.s("{[1]}").format(seq) == self.s("42") + big = self.s("{[1092837041982035981720398471029384012937412]}") + raises(ValueError, big.format, [0]) def test_getitem(self): d = {"hi" : 32} @@ -177,6 +181,10 @@ assert format(self.i(6), "=+3") == "+ 6" assert format(self.i(6), "a^3") == "a6a" + def test_width_overflow(self): + big = "92387405982730948052983740958230948524" + raises(ValueError, format, self.i(2), big) + def test_sign(self): assert format(self.i(-6)) == "-6" assert format(self.i(-6), "-") == "-6" From afa at codespeak.net Tue Jun 8 17:58:01 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 17:58:01 +0200 (CEST) Subject: [pypy-svn] r75202 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608155801.2A6C5282BDE@codespeak.net> Author: afa Date: Tue Jun 8 17:57:59 2010 New Revision: 75202 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: progress Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 17:57:59 2010 @@ -115,14 +115,6 @@ for name in ("pypy_decl.h", "pypy_macros.h"): udir.join(name).copy(interfaces_dir / name) -class BaseGlobalObject: - """Base class for all objects (pointers and structures)""" - - @classmethod - def declare(cls, *args, **kwargs): - obj = cls(*args, **kwargs) - GLOBALS[obj.name] = obj - _NOT_SPECIFIED = object() CANNOT_FAIL = object() @@ -342,18 +334,32 @@ INIT_FUNCTIONS = [] BOOTSTRAP_FUNCTIONS = [] +class BaseGlobalObject: + """Base class for all objects (pointers and structures)""" + + @classmethod + def declare(cls, *args, **kwargs): + obj = cls(*args, **kwargs) + GLOBALS[obj.name] = obj + class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name + '#' self.type = 'PyObject*' self.expr = expr + def get_global_code_for_bridge(self): + return [] + class GlobalStructurePointer(BaseGlobalObject): def __init__(self, name, type, expr): self.name = name self.type = type self.expr = expr + def get_global_code_for_bridge(self): + return ['%s _%s;' % (self.type, self.name)] + class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): self.name = 'PyExc_' + exc_name @@ -361,12 +367,18 @@ self.expr = ('space.gettypeobject(interp_exceptions.W_%s.typedef)' % (exc_name,)) + def get_global_code_for_bridge(self): + return ['%s _%s;' % (self.type[:-1], self.name)] + class GlobalTypeObject(BaseGlobalObject): def __init__(self, name, expr): self.name = 'Py%s_Type#' % (name,) self.type = 'PyTypeObject*' self.expr = expr + def get_global_code_for_bridge(self): + return [] + GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') @@ -648,14 +660,7 @@ global_objects = [] for obj in GLOBALS.values(): - if "#" in obj.name: - continue - if obj.type == 'PyDateTime_CAPI*': - global_objects.append('%s _%s;' % (obj.type, obj.name)) - elif obj.name.startswith('PyExc_'): - global_objects.append('%s _%s;' % (obj.type[:-1], obj.name)) - else: - global_objects.append('%s %s = NULL;' % (obj.typ, obj.name)) + global_objects.extend(obj.get_global_code_for_bridge()) global_code = '\n'.join(global_objects) prologue = "#include \n" From afa at codespeak.net Tue Jun 8 18:03:05 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 18:03:05 +0200 (CEST) Subject: [pypy-svn] r75203 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608160305.6F467282BDE@codespeak.net> Author: afa Date: Tue Jun 8 18:03:03 2010 New Revision: 75203 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: more progress in refactoring Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 18:03:03 2010 @@ -334,6 +334,17 @@ INIT_FUNCTIONS = [] BOOTSTRAP_FUNCTIONS = [] +def attach_and_track(space, py_obj, w_obj): + from pypy.module.cpyext.pyobject import ( + track_reference, get_typedescr, make_ref) + w_type = space.type(w_obj) + typedescr = get_typedescr(w_type.instancetypedef) + py_obj.c_ob_refcnt = 1 + py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, + make_ref(space, w_type)) + typedescr.attach(space, py_obj, w_obj) + track_reference(space, py_obj, w_obj) + class BaseGlobalObject: """Base class for all objects (pointers and structures)""" @@ -342,6 +353,10 @@ obj = cls(*args, **kwargs) GLOBALS[obj.name] = obj + def eval(self, space): + from pypy.module import cpyext + return eval(self.expr) + class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name + '#' @@ -683,8 +698,9 @@ # populate static data for obj in GLOBALS.values(): - from pypy.module import cpyext - w_obj = eval(obj.expr) + value = obj.eval(space) + INTERPLEVEL_API[name] = value + if obj.name.endswith('#'): name = obj.name[:-1] isptr = False @@ -694,15 +710,13 @@ if name.startswith('PyExc_'): isptr = False - INTERPLEVEL_API[name] = w_obj - name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) if obj.type == 'PyObject*': - value = make_ref(space, w_obj) + value = make_ref(space, value) elif obj.type == 'PyDateTime_CAPI*': - value = w_obj + value = value else: assert False, "Unknown static pointer: %s %s" % (typ, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), @@ -716,15 +730,7 @@ # we have a structure, get its address in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) - from pypy.module.cpyext.pyobject import ( - track_reference, get_typedescr) - w_type = space.type(w_obj) - typedescr = get_typedescr(w_type.instancetypedef) - py_obj.c_ob_refcnt = 1 - py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, - make_ref(space, w_type)) - typedescr.attach(space, py_obj, w_obj) - track_reference(space, py_obj, w_obj) + attach_and_track(space, py_obj, value) else: assert False, "Unknown static object: %s %s" % (typ, name) @@ -898,8 +904,7 @@ name = obj.name.replace("#", "") if name.startswith('PyExc_'): name = '_' + name - from pypy.module import cpyext - w_obj = eval(obj.expr) + value = obj.eval(space) if obj.type in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) elif obj.type == 'PyDateTime_CAPI*': From afa at codespeak.net Tue Jun 8 18:07:01 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 18:07:01 +0200 (CEST) Subject: [pypy-svn] r75204 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608160701.A57B3282BDE@codespeak.net> Author: afa Date: Tue Jun 8 18:07:00 2010 New Revision: 75204 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: progress Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 18:07:00 2010 @@ -375,6 +375,12 @@ def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type, self.name)] + def set_value_in_ctypes_dll(self, dll, value): + name = self.name.replace('Py', 'PyPy') + ptr = ctypes.c_void_p.in_dll(dll, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), + ctypes.c_void_p).value + class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): self.name = 'PyExc_' + exc_name @@ -701,27 +707,16 @@ value = obj.eval(space) INTERPLEVEL_API[name] = value - if obj.name.endswith('#'): - name = obj.name[:-1] - isptr = False - else: - name = obj.name - isptr = True - if name.startswith('PyExc_'): - isptr = False - - name = name.replace('Py', 'PyPy') - if isptr: - ptr = ctypes.c_void_p.in_dll(bridge, name) - if obj.type == 'PyObject*': - value = make_ref(space, value) - elif obj.type == 'PyDateTime_CAPI*': - value = value - else: - assert False, "Unknown static pointer: %s %s" % (typ, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), - ctypes.c_void_p).value + if isinstance(obj, GlobalStructurePointer): + obj.set_value_in_ctypes_dll(bridge, value) elif obj.type in ('PyObject*', 'PyTypeObject*'): + if obj.name.endswith('#'): + name = obj.name[:-1] + else: + name = obj.name + + name = name.replace('Py', 'PyPy') + if name.startswith('PyPyExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) From exarkun at codespeak.net Tue Jun 8 18:12:11 2010 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 8 Jun 2010 18:12:11 +0200 (CEST) Subject: [pypy-svn] r75205 - in pypy/trunk/pypy/module/zipimport: . test Message-ID: <20100608161211.0B0D3282BDE@codespeak.net> Author: exarkun Date: Tue Jun 8 18:12:09 2010 New Revision: 75205 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: Set the `__path__` attribute of packages loaded from zip files correctly The path in `__path__` should represent the directory from which the package was imported; previously it was the path to the zipfile itself. Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Tue Jun 8 18:12:09 2010 @@ -242,7 +242,7 @@ pass else: if is_package: - pkgpath = self.name + pkgpath = self.name + '/' + filename else: pkgpath = None try: Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Tue Jun 8 18:12:09 2010 @@ -201,7 +201,7 @@ self.writefile(self, "xxuuu/__init__.py", "") self.writefile(self, "xxuuu/yy.py", "def f(x): return x") mod = __import__("xxuuu", globals(), locals(), ['yy']) - assert mod.__path__ + assert mod.__path__ == [self.zipfile + "/xxuuu"] assert mod.yy.f(3) == 3 def test_functions(self): From arigo at codespeak.net Tue Jun 8 18:14:35 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jun 2010 18:14:35 +0200 (CEST) Subject: [pypy-svn] r75206 - pypy/branch/blackhole-improvement-merge Message-ID: <20100608161435.2511A282BDE@codespeak.net> Author: arigo Date: Tue Jun 8 18:14:33 2010 New Revision: 75206 Added: pypy/branch/blackhole-improvement-merge/ (props changed) - copied from r75205, pypy/trunk/ Log: A fresh branch in which to merge blackhole-improvement. From benjamin at codespeak.net Tue Jun 8 18:15:41 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 8 Jun 2010 18:15:41 +0200 (CEST) Subject: [pypy-svn] r75207 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100608161541.B9CD7282BDE@codespeak.net> Author: benjamin Date: Tue Jun 8 18:15:40 2010 New Revision: 75207 Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Log: fix padding with grouped digits Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 8 18:15:40 2010 @@ -493,7 +493,8 @@ buf.extend(thousands_sep) for i in range(d_state - 1, d_state - n_chars - 1, -1): buf.append(digits[i]) - buf.extend(digits[d_state:d_state - n_chars]) + for i in range(n_zeros): + buf.append("0") def _group_digits(self, spec, digits): buf = [] @@ -515,14 +516,14 @@ previous = group else: group = previous - final_grouping = min(group, max(group, min_width, 1)) + final_grouping = min(group, max(left, min_width, 1)) n_zeros = max(0, final_grouping - left) n_chars = max(0, min(left, final_grouping)) ts = self._loc_thousands if need_separator else None self._fill_digits(buf, digits, left, n_chars, n_zeros, ts) need_separator = True left -= n_chars - min_width -= 1 + min_width -= final_grouping if left <= 0 and min_width <= 0: done = True break Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Tue Jun 8 18:15:40 2010 @@ -180,6 +180,7 @@ assert format(self.i(6), "=3") == " 6" assert format(self.i(6), "=+3") == "+ 6" assert format(self.i(6), "a^3") == "a6a" + assert format(self.i(6), "03") == "006" def test_width_overflow(self): big = "92387405982730948052983740958230948524" @@ -200,6 +201,8 @@ assert format(self.i(123456789), ",") == "123,456,789" assert format(self.i(12345), "7,") == " 12,345" assert format(self.i(12345), "<7,") == "12,345 " + assert format(self.i(1234), "0=10,") == "00,001,234" + assert format(self.i(1234), "010,") == "00,001,234" class AppTestIntFormatting(BaseIntegralFormattingTest): From benjamin at codespeak.net Tue Jun 8 18:24:33 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 8 Jun 2010 18:24:33 +0200 (CEST) Subject: [pypy-svn] r75208 - pypy/branch/fast-forward/pypy/objspace/std Message-ID: <20100608162433.7C268282BDE@codespeak.net> Author: benjamin Date: Tue Jun 8 18:24:31 2010 New Revision: 75208 Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py Log: a few more float related lines Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 8 18:24:31 2010 @@ -730,6 +730,12 @@ tp = self._type if tp == "\0": tp = "g" + value = space.float_w(w_float) + if tp == "%": + tp = "f" + value *= 100 + if self._precision = -1: + self._precision = 6 def format_float(self, w_float): space = self.space From arigo at codespeak.net Tue Jun 8 18:50:25 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jun 2010 18:50:25 +0200 (CEST) Subject: [pypy-svn] r75209 - pypy/trunk/pypy/jit/metainterp/test Message-ID: <20100608165025.44182282BDE@codespeak.net> Author: arigo Date: Tue Jun 8 18:50:23 2010 New Revision: 75209 Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Log: Add a comment about the goal of the test. Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Tue Jun 8 18:50:23 2010 @@ -2587,6 +2587,7 @@ self.optimize_loop(ops, 'Not, Not', ops) def test_call_pure_invalidates_caches(self): + # CALL_PURE should still force the setfield_gc() to occur before it ops = ''' [p1, i1] setfield_gc(p1, i1, descr=valuedescr) From afa at codespeak.net Tue Jun 8 18:51:46 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 18:51:46 +0200 (CEST) Subject: [pypy-svn] r75210 - in pypy/trunk/pypy/lib: . test2 Message-ID: <20100608165146.53792282BDE@codespeak.net> Author: afa Date: Tue Jun 8 18:51:44 2010 New Revision: 75210 Added: pypy/trunk/pypy/lib/test2/test_dbm_extra.py (contents, props changed) Modified: pypy/trunk/pypy/lib/dbm.py Log: issue467 resolved: add checks to the dbm module, avoids some segfaults Modified: pypy/trunk/pypy/lib/dbm.py ============================================================================== --- pypy/trunk/pypy/lib/dbm.py (original) +++ pypy/trunk/pypy/lib/dbm.py Tue Jun 8 18:51:44 2010 @@ -1,4 +1,4 @@ -from ctypes import * +from ctypes import Structure, c_char_p, c_int, c_void_p, CDLL import ctypes.util import os, sys @@ -15,6 +15,11 @@ ('dsize', c_int), ] + def __init__(self, text): + if not isinstance(text, str): + raise TypeError("datum: expected string, not %s" % type(text)) + Structure.__init__(self, text, len(text)) + class dbm(object): def __init__(self, dbmobj): self._aobj = dbmobj @@ -42,9 +47,7 @@ def get(self, key, default=None): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] @@ -65,12 +68,8 @@ def __setitem__(self, key, value): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) - data = datum() - data.dptr = c_char_p(value) - data.dsize = c_int(len(value)) + dat = datum(key) + data = datum(value) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_REPLACE) if getattr(lib, funcs['error'])(self._aobj): getattr(lib, funcs['clearerr'])(self._aobj) @@ -80,15 +79,11 @@ def setdefault(self, key, default=''): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] - data = datum() - data.dptr = c_char_p(default) - data.dsize = c_int(len(default)) + data = datum(default) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_INSERT) if status < 0: getattr(lib, funcs['clearerr'])(self._aobj) @@ -98,9 +93,7 @@ def has_key(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return True @@ -109,9 +102,7 @@ def __delitem__(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) status = getattr(lib, funcs['delete'])(self._aobj, dat) if status < 0: raise KeyError(key) @@ -146,7 +137,7 @@ library = "GNU gdbm" funcs = {} -_init_func('open', [c_char_p, c_int, c_int]) +_init_func('open', (c_char_p, c_int, c_int)) _init_func('close', restype=c_void_p) _init_func('firstkey', restype=datum) _init_func('nextkey', restype=datum) @@ -160,6 +151,9 @@ def open(filename, flag='r', mode=0666): "open a DBM database" + if not isinstance(filename, str): + raise TypeError("expected string") + openflag = 0 try: @@ -177,3 +171,6 @@ if a_db == 0: raise error("Could not open file %s.db" % filename) return dbm(a_db) + +__all__ = ('datum', 'dbm', 'error', 'funcs', 'open', 'library') + Added: pypy/trunk/pypy/lib/test2/test_dbm_extra.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/lib/test2/test_dbm_extra.py Tue Jun 8 18:51:44 2010 @@ -0,0 +1,8 @@ +try: + from pypy.lib import dbm +except ImportError: + py.test.skip("No dbm module on this platform") + +def test_extra(): + py.test.raises(TypeError, dbm.datum, 123) + py.test.raises(TypeError, dbm.datum, False) From arigo at codespeak.net Tue Jun 8 19:48:47 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jun 2010 19:48:47 +0200 (CEST) Subject: [pypy-svn] r75211 - in pypy/branch/blackhole-improvement-merge/pypy: annotation annotation/test jit/backend jit/backend/llgraph jit/backend/llgraph/test jit/backend/llsupport jit/backend/llsupport/test jit/backend/test jit/backend/x86 jit/backend/x86/test jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/test jit/tl jit/tl/spli jit/tl/tla jit/tool jit/tool/test module/pypyjit module/pypyjit/test objspace/flow rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gctransform/test rpython/memory/test rpython/test tool/algo tool/algo/test translator/c translator/c/src translator/c/test translator/tool Message-ID: <20100608174847.63D29282BDE@codespeak.net> Author: arigo Date: Tue Jun 8 19:48:40 2010 New Revision: 75211 Added: pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/ (props changed) - copied from r75210, pypy/branch/blackhole-improvement/pypy/jit/codewriter/ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/blackhole.py - copied unchanged from r75210, pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitexc.py - copied unchanged from r75210, pypy/branch/blackhole-improvement/pypy/jit/metainterp/jitexc.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_immutable.py - copied unchanged from r75210, pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_immutable.py pypy/branch/blackhole-improvement-merge/pypy/tool/algo/color.py - copied unchanged from r75210, pypy/branch/blackhole-improvement/pypy/tool/algo/color.py pypy/branch/blackhole-improvement-merge/pypy/tool/algo/test/test_color.py - copied unchanged from r75210, pypy/branch/blackhole-improvement/pypy/tool/algo/test/test_color.py Removed: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/codewriter.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/dump.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/effectinfo.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/heaptracker.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/policy.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/support.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_codewriter.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_effectinfo.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_support.py Modified: pypy/branch/blackhole-improvement-merge/pypy/annotation/builtin.py pypy/branch/blackhole-improvement-merge/pypy/annotation/description.py pypy/branch/blackhole-improvement-merge/pypy/annotation/test/test_annrpython.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/llimpl.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/runner.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/descr.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/gc.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/llmodel.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_descr.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_gc.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/model.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/runner_test.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_ll_random.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_random.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/assembler.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/regalloc.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/ri386.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/runner.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/support.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_basic.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_gc_integration.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc2.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_runner.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_send.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_ztranslation.py pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/support.py pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/test/ (props changed) pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/compile.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/executor.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/history.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitprof.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/logger.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizefindnode.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeopt.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeutil.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resoperation.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resume.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/simple_optimize.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/specnode.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/oparser.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_basic.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_blackhole.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_compile.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_exception.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_executor.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_history.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_jitprof.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_list.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_loop.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizefindnode.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizeopt.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_pyjitpl.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_recursive.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_resume.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_send.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_slist.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_string.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tl.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tlc.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtual.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualref.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmstate.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_ztranslation.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/typesystem.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualizable.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualref.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmspot.py pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmstate.py pypy/branch/blackhole-improvement-merge/pypy/jit/tl/spli/interpreter.py pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tl.py pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tla/tla.py pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlc.py pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlr.py pypy/branch/blackhole-improvement-merge/pypy/jit/tool/jitoutput.py pypy/branch/blackhole-improvement-merge/pypy/jit/tool/test/test_jitoutput.py pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/policy.py pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/test/test_pypy_c.py pypy/branch/blackhole-improvement-merge/pypy/objspace/flow/model.py pypy/branch/blackhole-improvement-merge/pypy/rpython/llinterp.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llarena.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llmemory.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lloperation.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lltype.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/rclass.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_boehm.py pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/test/test_lldict.py pypy/branch/blackhole-improvement-merge/pypy/rpython/raddress.py pypy/branch/blackhole-improvement-merge/pypy/rpython/rbuiltin.py pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_exception.py pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_llann.py pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rdict.py pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rptr.py pypy/branch/blackhole-improvement-merge/pypy/translator/c/primitive.py pypy/branch/blackhole-improvement-merge/pypy/translator/c/src/address.h pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_genc.py pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_lladdresses.py pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_refcount.py pypy/branch/blackhole-improvement-merge/pypy/translator/tool/make_dot.py Log: Attempt to merge the branch blackhole-improvement into trunk. Will run all tests... Modified: pypy/branch/blackhole-improvement-merge/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/annotation/builtin.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/annotation/builtin.py Tue Jun 8 19:48:40 2010 @@ -346,7 +346,7 @@ assert s_type.is_constant() return SomePtr(s_type.const) -def llmemory_cast_adr_to_int(s): +def llmemory_cast_adr_to_int(s, s_mode=None): return SomeInteger() # xxx def llmemory_cast_int_to_adr(s): Modified: pypy/branch/blackhole-improvement-merge/pypy/annotation/description.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/annotation/description.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/annotation/description.py Tue Jun 8 19:48:40 2010 @@ -539,9 +539,18 @@ try: args.fixedunpack(0) except ValueError: - raise Exception("default __init__ takes no argument" " (class %s)" % (self.name,)) + elif self.pyobj is Exception: + # check explicitly against "raise Exception, x" where x + # is a low-level exception pointer + try: + [s_arg] = args.fixedunpack(1) + except ValueError: + pass + else: + from pypy.annotation.model import SomePtr + assert not isinstance(s_arg, SomePtr) else: # call the constructor args = args.prepend(s_instance) Modified: pypy/branch/blackhole-improvement-merge/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/annotation/test/test_annrpython.py Tue Jun 8 19:48:40 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + # + def f(): + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise Exception, lle + # ^^^ instead, must cast back from a base ptr to an instance + a = self.RPythonAnnotator() + py.test.raises(AssertionError, a.build_types, f, []) + def test_unicode_decode_error(self): def f(): try: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/llimpl.py Tue Jun 8 19:48:40 2010 @@ -7,9 +7,10 @@ import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel -from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, +from pypy.jit.metainterp.history import (ConstInt, ConstPtr, BoxInt, BoxPtr, BoxObj, BoxFloat, REF, INT, FLOAT) +from pypy.jit.codewriter import heaptracker from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport @@ -73,12 +74,12 @@ 'int_eq' : (('int', 'int'), 'bool'), 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), + 'int_is_zero' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), - 'bool_not' : (('bool',), 'bool'), 'uint_add' : (('int', 'int'), 'int'), 'uint_sub' : (('int', 'int'), 'int'), 'uint_mul' : (('int', 'int'), 'int'), @@ -103,7 +104,6 @@ 'float_ge' : (('float', 'float'), 'bool'), 'float_neg' : (('float',), 'float'), 'float_abs' : (('float',), 'float'), - 'float_is_true' : (('float',), 'bool'), 'cast_float_to_int':(('float',), 'int'), 'cast_int_to_float':(('int',), 'float'), 'same_as' : (('int',), 'int'), # could also be ptr=>ptr @@ -155,16 +155,6 @@ 'force_token' : ((), 'int'), 'call_may_force' : (('int', 'varargs'), 'intorptr'), 'guard_not_forced': ((), None), - 'virtual_ref' : (('ref', 'int'), 'ref'), - 'virtual_ref_finish': (('ref', 'ref'), None), - #'getitem' : (('void', 'ref', 'int'), 'int'), - #'setitem' : (('void', 'ref', 'int', 'int'), None), - #'newlist' : (('void', 'varargs'), 'ref'), - #'append' : (('void', 'ref', 'int'), None), - #'insert' : (('void', 'ref', 'int', 'int'), None), - #'pop' : (('void', 'ref',), 'int'), - #'len' : (('void', 'ref',), 'int'), - #'listnonzero' : (('void', 'ref',), 'int'), } # ____________________________________________________________ @@ -231,19 +221,19 @@ else: return repr(x) -def repr_list(lst, types, memocast): +def repr_list(lst, types): res_l = [] if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, memocast)) + res_l.append('(%s)' % repr1(elem, tp)) else: - res_l.append(repr1(elem, tp, memocast)) + res_l.append(repr1(elem, tp)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, memocast): +def repr1(x, tp): if tp == "intorptr": TYPE = lltype.typeOf(x) if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': @@ -259,7 +249,7 @@ return '(* None)' if isinstance(x, int): # XXX normalize? - ptr = str(cast_int_to_adr(memocast, x)) + ptr = str(llmemory.cast_int_to_adr(x)) elif isinstance(ootype.typeOf(x), ootype.OOType): return repr(x) else: @@ -400,10 +390,9 @@ class Frame(object): OPHANDLERS = [None] * (rop._LAST+1) - def __init__(self, memocast, cpu): + def __init__(self, cpu): self.verbose = False self.cpu = cpu - self.memocast = memocast self.opindex = 1 self._forced = False self._may_force = -1 @@ -522,15 +511,14 @@ elif res is NotImplemented: resdata = '*fail*' else: - resdata = '-> ' + repr1(res, restype, self.memocast) + resdata = '-> ' + repr1(res, restype) # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), + log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes), resdata)) return res def as_int(self, x): - return cast_to_int(x, self.memocast) + return cast_to_int(x) def as_ptr(self, x): return cast_to_ptr(x) @@ -554,34 +542,36 @@ try: op = getattr(cls, 'op_' + opname.lower()) # op_guard_true etc. except AttributeError: - name = 'do_' + opname.lower() try: - impl = globals()[name] # do_arraylen_gc etc. + impl = globals()['do_' + opname.lower()] # do_arraylen_gc etc. def op(self, descr, *args): - return impl(descr, *args) - # + if descr is None: + return impl(*args) + else: + return impl(descr, *args) except KeyError: - from pypy.jit.backend.llgraph import llimpl - impl = getattr(executor, name) # do_int_add etc. - def _op_default_implementation(self, descr, *args): - # for all operations implemented in execute.py - boxedargs = [] - for x in args: - if type(x) is int: - boxedargs.append(BoxInt(x)) - elif type(x) is float: - boxedargs.append(BoxFloat(x)) - elif isinstance(ootype.typeOf(x), ootype.OOType): - boxedargs.append(BoxObj(ootype.cast_to_object(x))) - else: - boxedargs.append(BoxPtr(x)) - # xxx this passes the 'llimpl' module as the CPU argument - resbox = impl(llimpl, *boxedargs) - return getattr(resbox, 'value', None) - op = _op_default_implementation - # + op = cls._make_impl_from_blackhole_interp(opname) cls.OPHANDLERS[opnum] = op + @classmethod + def _make_impl_from_blackhole_interp(cls, opname): + from pypy.jit.metainterp.blackhole import BlackholeInterpreter + name = 'bhimpl_' + opname.lower() + func = BlackholeInterpreter.__dict__[name] + for argtype in func.argtypes: + assert argtype in ('i', 'r', 'f') + # + def _op_default_implementation(self, descr, *args): + # for all operations implemented in the blackhole interpreter + return func(*args) + # + return _op_default_implementation + + def op_debug_merge_point(self, _, value): + from pypy.jit.metainterp.warmspot import get_stats + loc = ConstPtr(value)._get_str() + get_stats().add_merge_point_location(loc) + def op_guard_true(self, _, value): if not value: raise GuardFailed @@ -596,7 +586,7 @@ def op_guard_class(self, _, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_class), + llmemory.cast_int_to_adr(expected_class), rclass.CLASSTYPE) if value.typeptr != expected_class: raise GuardFailed @@ -630,7 +620,7 @@ def _cast_exception(self, exception): return llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, exception), + llmemory.cast_int_to_adr(exception), rclass.CLASSTYPE) def _issubclass(self, cls1, cls2): @@ -696,7 +686,7 @@ if arraydescr.typeinfo == REF: return do_getarrayitem_gc_ptr(array, index) elif arraydescr.typeinfo == INT: - return do_getarrayitem_gc_int(array, index, self.memocast) + return do_getarrayitem_gc_int(array, index) elif arraydescr.typeinfo == FLOAT: return do_getarrayitem_gc_float(array, index) else: @@ -708,7 +698,7 @@ if fielddescr.typeinfo == REF: return do_getfield_gc_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_gc_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: return do_getfield_gc_float(struct, fielddescr.ofs) else: @@ -718,11 +708,11 @@ def op_getfield_raw(self, fielddescr, struct): if fielddescr.typeinfo == REF: - return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: - return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_float(struct, fielddescr.ofs) else: raise NotImplementedError @@ -733,17 +723,17 @@ def op_new_with_vtable(self, descr, vtable): assert descr is None - size = get_class_size(self.memocast, vtable) - result = do_new(size) + descr = heaptracker.vtable2descr(self.cpu, vtable) + result = do_new(descr.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) - value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) + value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr.typeinfo == REF: do_setarrayitem_gc_ptr(array, index, newvalue) elif arraydescr.typeinfo == INT: - do_setarrayitem_gc_int(array, index, newvalue, self.memocast) + do_setarrayitem_gc_int(array, index, newvalue) elif arraydescr.typeinfo == FLOAT: do_setarrayitem_gc_float(array, index, newvalue) else: @@ -753,8 +743,7 @@ if fielddescr.typeinfo == REF: do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_gc_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: do_setfield_gc_float(struct, fielddescr.ofs, newvalue) else: @@ -762,30 +751,41 @@ def op_setfield_raw(self, fielddescr, struct, newvalue): if fielddescr.typeinfo == REF: - do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: - do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_float(struct, fielddescr.ofs, newvalue) else: raise NotImplementedError def op_call(self, calldescr, func, *args): - _call_args[:] = args - if calldescr.typeinfo == 'v': - err_result = None - elif calldescr.typeinfo == REF: - err_result = lltype.nullptr(llmemory.GCREF.TO) - elif calldescr.typeinfo == INT: - err_result = 0 - elif calldescr.typeinfo == FLOAT: - err_result = 0.0 - else: - raise NotImplementedError - return _do_call_common(func, self.memocast, err_result) + global _last_exception + assert _last_exception is None, "exception left behind" + assert _call_args_i == _call_args_r == _call_args_f == [] + args_in_order = [] + for x in args: + T = lltype.typeOf(x) + if T is lltype.Signed: + args_in_order.append('i') + _call_args_i.append(x) + elif T == llmemory.GCREF: + args_in_order.append('r') + _call_args_r.append(x) + elif T is lltype.Float: + args_in_order.append('f') + _call_args_f.append(x) + else: + raise TypeError(x) + try: + return _do_call_common(func, args_in_order) + except LLException, lle: + _last_exception = lle + d = {'v': None, + REF: lltype.nullptr(llmemory.GCREF.TO), + INT: 0, + FLOAT: 0.0} + return d[calldescr.typeinfo] op_call_pure = op_call @@ -801,7 +801,7 @@ return do_new_array(arraydescr.ofs, count) def op_cast_ptr_to_int(self, descr, ptr): - return cast_to_int(ptr, self.memocast) + return cast_to_int(ptr) def op_uint_xor(self, descr, arg1, arg2): return arg1 ^ arg2 @@ -859,12 +859,6 @@ if forced: raise GuardFailed - def op_virtual_ref(self, _, virtual, index): - return virtual - - def op_virtual_ref_finish(self, _, vref, virtual): - pass - class OOFrame(Frame): @@ -925,7 +919,7 @@ def op_call(self, calldescr, func, *args): sm = ootype.cast_from_object(calldescr.FUNC, func) - newargs = cast_call_args(calldescr.FUNC.ARGS, args, self.memocast) + newargs = cast_call_args(calldescr.FUNC.ARGS, args) res = call_maybe_on_top_of_llinterp(sm, newargs) if isinstance(calldescr.FUNC.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -937,7 +931,7 @@ METH = descr.METH obj = ootype.cast_from_object(descr.SELFTYPE, obj) meth = getattr(obj, descr.methname) - newargs = cast_call_args(METH.ARGS, args, self.memocast) + newargs = cast_call_args(METH.ARGS, args) res = call_maybe_on_top_of_llinterp(meth, newargs) if isinstance(METH.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -973,27 +967,27 @@ # ____________________________________________________________ -def cast_to_int(x, memocast): +def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): - return cast_adr_to_int(memocast, llmemory.cast_ptr_to_adr(x)) + return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return cast_adr_to_int(memocast, x) + return heaptracker.adr2int(x) return lltype.cast_primitive(lltype.Signed, x) -def cast_from_int(TYPE, x, memocast): +def cast_from_int(TYPE, x): if isinstance(TYPE, lltype.Ptr): - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) elif TYPE == llmemory.Address: - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) assert lltype.typeOf(x) == llmemory.Address return x else: if lltype.typeOf(x) == llmemory.Address: - x = cast_adr_to_int(memocast, x) + x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x) def cast_to_ptr(x): @@ -1013,11 +1007,11 @@ return x -def new_frame(memocast, is_oo, cpu): +def new_frame(is_oo, cpu): if is_oo: - frame = OOFrame(memocast, cpu) + frame = OOFrame(cpu) else: - frame = Frame(memocast, cpu) + frame = Frame(cpu) return _to_opaque(frame) _future_values = [] @@ -1067,69 +1061,68 @@ def frame_int_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Signed + return x def frame_float_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Float + return x def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - result = frame.fail_args[num] - frame.fail_args[num] = None - return result + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) == llmemory.GCREF + return x -_last_exception = None +def frame_get_value_count(frame): + frame = _from_opaque(frame) + return len(frame.fail_args) -def get_exception(): - if _last_exception: - return llmemory.cast_ptr_to_adr(_last_exception.args[0]) - else: - return llmemory.NULL +def frame_clear_latest_values(frame, count): + frame = _from_opaque(frame) + assert count == len(frame.fail_args) + del frame.fail_args -def get_exc_value(): - if _last_exception: - return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) - else: - return lltype.nullptr(llmemory.GCREF.TO) +_last_exception = None -def clear_exception(): +def grab_exc_value(): global _last_exception - _last_exception = None + if _last_exception is not None: + result = _last_exception.args[1] + _last_exception = None + return lltype.cast_opaque_ptr(llmemory.GCREF, result) + else: + return lltype.nullptr(llmemory.GCREF.TO) -_pseudo_exceptions = {} +##_pseudo_exceptions = {} -def _get_error(Class): - if _llinterp.typer is not None: - llframe = _llinterp.frame_class(None, None, _llinterp) - try: - llframe.make_llexception(Class()) - except LLException, e: - return e - else: - assert 0, "should have raised" - else: - # for tests, a random emulated ll_inst will do - if Class not in _pseudo_exceptions: - ll_inst = lltype.malloc(rclass.OBJECT, zero=True) - ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, - immortal=True) - _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) - return _pseudo_exceptions[Class] - -def get_overflow_error(): - return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0]) - -def get_overflow_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(OverflowError).args[1]) - -def get_zero_division_error(): - return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0]) - -def get_zero_division_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(ZeroDivisionError).args[1]) +##def _get_error(Class): +## if _llinterp.typer is not None: +## llframe = _llinterp.frame_class(None, None, _llinterp) +## try: +## llframe.make_llexception(Class()) +## except LLException, e: +## return e +## else: +## assert 0, "should have raised" +## else: +## # for tests, a random emulated ll_inst will do +## if Class not in _pseudo_exceptions: +## ll_inst = lltype.malloc(rclass.OBJECT, zero=True) +## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, +## immortal=True) +## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) +## return _pseudo_exceptions[Class] + +##def get_overflow_error_value(): +## return lltype.cast_opaque_ptr(llmemory.GCREF, +## _get_error(OverflowError).args[1]) def force(opaque_frame): frame = _from_opaque(opaque_frame) @@ -1151,40 +1144,30 @@ def get_frame_forced_token(opaque_frame): return llmemory.cast_ptr_to_adr(opaque_frame) -class MemoCast(object): - def __init__(self): - self.addresses = [llmemory.NULL] - self.rev_cache = {} - self.vtable_to_size = {} - -def new_memo_cast(): - memocast = MemoCast() - return _to_opaque(memocast) - -def cast_adr_to_int(memocast, adr): - # xxx slow - assert lltype.typeOf(adr) == llmemory.Address - memocast = _from_opaque(memocast) - addresses = memocast.addresses - for i in xrange(len(addresses)-1, -1, -1): - if addresses[i] == adr: - return i - i = len(addresses) - addresses.append(adr) - return i - -def cast_int_to_adr(memocast, int): - memocast = _from_opaque(memocast) - assert 0 <= int < len(memocast.addresses) - return memocast.addresses[int] - -def get_class_size(memocast, vtable): - memocast = _from_opaque(memocast) - return memocast.vtable_to_size[vtable] - -def set_class_size(memocast, vtable, size): - memocast = _from_opaque(memocast) - memocast.vtable_to_size[vtable] = size +##def cast_adr_to_int(memocast, adr): +## # xxx slow +## assert lltype.typeOf(adr) == llmemory.Address +## memocast = _from_opaque(memocast) +## addresses = memocast.addresses +## for i in xrange(len(addresses)-1, -1, -1): +## if addresses[i] == adr: +## return i +## i = len(addresses) +## addresses.append(adr) +## return i + +##def cast_int_to_adr(memocast, int): +## memocast = _from_opaque(memocast) +## assert 0 <= int < len(memocast.addresses) +## return memocast.addresses[int] + +##def get_class_size(memocast, vtable): +## memocast = _from_opaque(memocast) +## return memocast.vtable_to_size[vtable] + +##def set_class_size(memocast, vtable, size): +## memocast = _from_opaque(memocast) +## memocast.vtable_to_size[vtable] = size class GuardFailed(Exception): pass @@ -1192,29 +1175,32 @@ # ____________________________________________________________ +def do_same_as(x): + return x + def do_arraylen_gc(arraydescr, array): array = array._obj.container return array.getlength() -def do_strlen(_, string): +def do_strlen(string): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return len(str.chars) -def do_strgetitem(_, string, index): +def do_strgetitem(string, index): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) -def do_unicodelen(_, string): +def do_unicodelen(string): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return len(uni.chars) -def do_unicodegetitem(_, string, index): +def do_unicodegetitem(string, index): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return ord(uni.chars[index]) -def do_getarrayitem_gc_int(array, index, memocast): +def do_getarrayitem_gc_int(array, index): array = array._obj.container - return cast_to_int(array.getitem(index), memocast) + return cast_to_int(array.getitem(index)) def do_getarrayitem_gc_float(array, index): array = array._obj.container @@ -1229,8 +1215,8 @@ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_gc_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_gc(struct, fieldnum), memocast) +def do_getfield_gc_int(struct, fieldnum): + return cast_to_int(_getfield_gc(struct, fieldnum)) def do_getfield_gc_float(struct, fieldnum): return cast_to_float(_getfield_gc(struct, fieldnum)) @@ -1238,19 +1224,19 @@ def do_getfield_gc_ptr(struct, fieldnum): return cast_to_ptr(_getfield_gc(struct, fieldnum)) -def _getfield_raw(struct, fieldnum, memocast): +def _getfield_raw(struct, fieldnum): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_raw_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast) +def do_getfield_raw_int(struct, fieldnum): + return cast_to_int(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_float(struct, fieldnum, memocast): - return cast_to_float(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_float(struct, fieldnum): + return cast_to_float(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_ptr(struct, fieldnum, memocast): - return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_ptr(struct, fieldnum): + return cast_to_ptr(_getfield_raw(struct, fieldnum)) def do_new(size): TYPE = symbolic.Size2Type[size] @@ -1262,10 +1248,10 @@ x = lltype.malloc(TYPE, count, zero=True) return cast_to_ptr(x) -def do_setarrayitem_gc_int(array, index, newvalue, memocast): +def do_setarrayitem_gc_int(array, index, newvalue): array = array._obj.container ITEMTYPE = lltype.typeOf(array).OF - newvalue = cast_from_int(ITEMTYPE, newvalue, memocast) + newvalue = cast_from_int(ITEMTYPE, newvalue) array.setitem(index, newvalue) def do_setarrayitem_gc_float(array, index, newvalue): @@ -1280,11 +1266,11 @@ newvalue = cast_from_ptr(ITEMTYPE, newvalue) array.setitem(index, newvalue) -def do_setfield_gc_int(struct, fieldnum, newvalue, memocast): +def do_setfield_gc_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) def do_setfield_gc_float(struct, fieldnum, newvalue): @@ -1301,108 +1287,129 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_int(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_float(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_float(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_float(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_ptr(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_newstr(_, length): +def do_newstr(length): x = rstr.mallocstr(length) return cast_to_ptr(x) -def do_newunicode(_, length): +def do_newunicode(length): return cast_to_ptr(rstr.mallocunicode(length)) -def do_strsetitem(_, string, index, newvalue): +def do_strsetitem(string, index, newvalue): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) -def do_unicodesetitem(_, string, index, newvalue): +def do_unicodesetitem(string, index, newvalue): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) uni.chars[index] = unichr(newvalue) # ---------- call ---------- -_call_args = [] +_call_args_i = [] +_call_args_r = [] +_call_args_f = [] def do_call_pushint(x): - _call_args.append(x) - -def do_call_pushfloat(x): - _call_args.append(x) + _call_args_i.append(x) def do_call_pushptr(x): - _call_args.append(x) + _call_args_r.append(x) -def _do_call_common(f, memocast, err_result=None): - global _last_exception - assert _last_exception is None, "exception left behind" - ptr = cast_int_to_adr(memocast, f).ptr +def do_call_pushfloat(x): + _call_args_f.append(x) + +def _do_call_common(f, args_in_order=None): + ptr = llmemory.cast_int_to_adr(f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS - args = cast_call_args(ARGS, _call_args, memocast) - del _call_args[:] + args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f, + args_in_order) + del _call_args_i[:] + del _call_args_r[:] + del _call_args_f[:] assert len(ARGS) == len(args) - try: - if hasattr(ptr._obj, 'graph'): - llinterp = _llinterp # it's a global set here by CPU.__init__() - result = llinterp.eval_graph(ptr._obj.graph, args) - else: - result = ptr._obj._callable(*args) - except LLException, e: - _last_exception = e - result = err_result + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() + result = llinterp.eval_graph(ptr._obj.graph, args) + # ^^^ may raise, in which case we get an LLException + else: + result = ptr._obj._callable(*args) return result -def do_call_void(f, memocast): - _do_call_common(f, memocast) +def do_call_void(f): + _do_call_common(f) -def do_call_int(f, memocast): - x = _do_call_common(f, memocast, 0) - return cast_to_int(x, memocast) +def do_call_int(f): + x = _do_call_common(f) + return cast_to_int(x) -def do_call_float(f, memocast): - x = _do_call_common(f, memocast, 0) +def do_call_float(f): + x = _do_call_common(f) return cast_to_float(x) -def do_call_ptr(f, memocast): - x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO)) +def do_call_ptr(f): + x = _do_call_common(f) return cast_to_ptr(x) -def cast_call_args(ARGS, args, memocast): - argsiter = iter(args) +def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None): + argsiter_i = iter(args_i) + argsiter_r = iter(args_r) + argsiter_f = iter(args_f) + if args_in_order is not None: + orderiter = iter(args_in_order) args = [] for TYPE in ARGS: if TYPE is lltype.Void: x = None else: - x = argsiter.next() if isinstance(TYPE, ootype.OOType): + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = ootype.cast_from_object(TYPE, x) elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = cast_from_ptr(TYPE, x) elif TYPE is lltype.Float: + if args_in_order is not None: + n = orderiter.next() + assert n == 'f' + x = argsiter_f.next() x = cast_from_float(TYPE, x) else: - x = cast_from_int(TYPE, x, memocast) + if args_in_order is not None: + n = orderiter.next() + assert n == 'i' + x = argsiter_i.next() + x = cast_from_int(TYPE, x) args.append(x) - assert list(argsiter) == [] + assert list(argsiter_i) == [] + assert list(argsiter_r) == [] + assert list(argsiter_f) == [] return args @@ -1421,7 +1428,7 @@ result = llinterp.eval_graph(mymethod.graph, myargs) else: result = meth(*args) - except LLException, e: + except XXX-LLException, e: _last_exception = e result = get_err_result_for_type(mymethod._TYPE.RESULT) return result @@ -1474,16 +1481,13 @@ COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame")) -MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[OOFrame] = OOFRAME.TO -_TO_OPAQUE[MemoCast] = MEMOCAST.TO s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) s_Frame = annmodel.SomePtr(FRAME) -s_MemoCast = annmodel.SomePtr(MEMOCAST) setannotation(compile_start, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) @@ -1512,23 +1516,14 @@ setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) setannotation(frame_float_getvalue, annmodel.SomeFloat()) +setannotation(frame_get_value_count, annmodel.SomeInteger()) +setannotation(frame_clear_latest_values, annmodel.s_None) -setannotation(get_exception, annmodel.SomeAddress()) -setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(clear_exception, annmodel.s_None) -setannotation(get_overflow_error, annmodel.SomeAddress()) -setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(get_zero_division_error, annmodel.SomeAddress()) -setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF)) setannotation(force, annmodel.SomeInteger()) setannotation(get_forced_token_frame, s_Frame) setannotation(get_frame_forced_token, annmodel.SomeAddress()) -setannotation(new_memo_cast, s_MemoCast) -setannotation(cast_adr_to_int, annmodel.SomeInteger()) -setannotation(cast_int_to_adr, annmodel.SomeAddress()) -setannotation(set_class_size, annmodel.s_None) - setannotation(do_arraylen_gc, annmodel.SomeInteger()) setannotation(do_strlen, annmodel.SomeInteger()) setannotation(do_strgetitem, annmodel.SomeInteger()) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/runner.py Tue Jun 8 19:48:40 2010 @@ -15,6 +15,7 @@ from pypy.jit.backend import model from pypy.jit.backend.llgraph import llimpl, symbolic from pypy.jit.metainterp.typesystem import llhelper, oohelper +from pypy.jit.codewriter import heaptracker from pypy.rlib import rgc class MiniStats: @@ -23,11 +24,19 @@ class Descr(history.AbstractDescr): - def __init__(self, ofs, typeinfo, extrainfo=None, name=None): + def __init__(self, ofs, typeinfo, extrainfo=None, name=None, + arg_types=None): self.ofs = ofs self.typeinfo = typeinfo self.extrainfo = extrainfo self.name = name + self.arg_types = arg_types + + def get_arg_types(self): + return self.arg_types + + def get_return_type(self): + return self.typeinfo def get_extra_info(self): return self.extrainfo @@ -51,6 +60,9 @@ def is_array_of_floats(self): return self.typeinfo == FLOAT + def as_vtable_size_descr(self): + return self + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -86,7 +98,6 @@ self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.stats.exec_conditional_jumps = 0 - self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._llinterp = LLInterpreter(self.rtyper) self._future_values = [] @@ -96,22 +107,16 @@ assert self.translate_support_code return False - def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None): - key = (ofs, typeinfo, extrainfo, name) + def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None, + arg_types=None): + key = (ofs, typeinfo, extrainfo, name, arg_types) try: return self._descrs[key] except KeyError: - descr = Descr(ofs, typeinfo, extrainfo, name) + descr = Descr(ofs, typeinfo, extrainfo, name, arg_types) self._descrs[key] = descr return descr - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - for vtable, size in class_sizes.items(): - if not self.is_oo: - size = size.ofs - llimpl.set_class_size(self.memo_cast, vtable, size) - def compile_bridge(self, faildescr, inputargs, operations): c = llimpl.compile_start() self._compile_loop_or_bridge(c, inputargs, operations) @@ -161,8 +166,6 @@ llimpl.compile_add_int_const(c, x.value) elif isinstance(x, self.ts.ConstRef): llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) elif isinstance(x, history.ConstFloat): llimpl.compile_add_float_const(c, x.value) else: @@ -213,7 +216,7 @@ def _execute_token(self, loop_token): compiled_version = loop_token._llgraph_compiled_version - frame = llimpl.new_frame(self.memo_cast, self.is_oo, self) + frame = llimpl.new_frame(self.is_oo, self) # setup the frame llimpl.frame_clear(frame, compiled_version) # run the loop @@ -247,60 +250,22 @@ def get_latest_value_float(self, index): return llimpl.frame_float_getvalue(self.latest_frame, index) + def get_latest_value_count(self): + return llimpl.frame_get_value_count(self.latest_frame) + def get_latest_force_token(self): token = llimpl.get_frame_forced_token(self.latest_frame) - return self.cast_adr_to_int(token) + return heaptracker.adr2int(token) - def make_boxes_from_latest_values(self, faildescr): - inputargs_and_holes = [] - for i in range(len(faildescr._fail_args_types)): - boxtype = faildescr._fail_args_types[i] - if boxtype == history.INT: - box = history.BoxInt(self.get_latest_value_int(i)) - elif boxtype == history.REF: - box = self.ts.BoxRef(self.get_latest_value_ref(i)) - elif boxtype == history.FLOAT: - box = history.BoxFloat(self.get_latest_value_float(i)) - elif boxtype == history.HOLE: - box = None - else: - assert False, "bad box type: num=%d" % ord(boxtype) - inputargs_and_holes.append(box) - return inputargs_and_holes + def clear_latest_values(self, count): + llimpl.frame_clear_latest_values(self.latest_frame, count) # ---------- - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) - - def get_exc_value(self): - return llimpl.get_exc_value() - - def clear_exception(self): - llimpl.clear_exception() - - def get_overflow_error(self): - return (self.cast_adr_to_int(llimpl.get_overflow_error()), - llimpl.get_overflow_error_value()) - - def get_zero_division_error(self): - return (self.cast_adr_to_int(llimpl.get_zero_division_error()), - llimpl.get_zero_division_error_value()) - def sizeof(self, S): assert not isinstance(S, lltype.Ptr) return self.getdescr(symbolic.get_size(S)) - def cast_adr_to_int(self, adr): - return llimpl.cast_adr_to_int(self.memo_cast, adr) - - def cast_int_to_adr(self, int): - return llimpl.cast_int_to_adr(self.memo_cast, int) - - def cast_gcref_to_int(self, gcref): - return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref)) - - class LLtypeCPU(BaseCPU): is_oo = False @@ -316,14 +281,17 @@ return self.getdescr(ofs, token[0], name=fieldname) def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): + arg_types = [] + for ARG in ARGS: + token = history.getkind(ARG) + if token != 'void': + arg_types.append(token[0]) token = history.getkind(RESULT) - return self.getdescr(0, token[0], extrainfo=extrainfo) - - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) + return self.getdescr(0, token[0], extrainfo=extrainfo, + arg_types=''.join(arg_types)) - def get_exc_value(self): - return llimpl.get_exc_value() + def grab_exc_value(self): + return llimpl.grab_exc_value() def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) @@ -334,202 +302,151 @@ # ---------- the backend-dependent operations ---------- - def do_arraylen_gc(self, arraybox, arraydescr): - array = arraybox.getref_base() - return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - - def do_strlen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_strlen(0, string)) - - def do_strgetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_strgetitem(0, string, index)) - - def do_unicodelen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_unicodelen(0, string)) - - def do_unicodegetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_unicodegetitem(0, string, index)) + def bh_strlen(self, string): + return llimpl.do_strlen(string) + + def bh_strgetitem(self, string, index): + return llimpl.do_strgetitem(string, index) + + def bh_unicodelen(self, string): + return llimpl.do_unicodelen(string) + + def bh_unicodegetitem(self, string, index): + return llimpl.do_unicodegetitem(string, index) - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) - elif arraydescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, - self.memo_cast)) - elif arraydescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array, - index)) - else: - raise NotImplementedError + return llimpl.do_getarrayitem_gc_int(array, index) + def bh_getarrayitem_gc_r(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_ptr(array, index) + def bh_getarrayitem_gc_f(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_float(array, index) - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_gc_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, - fielddescr.ofs)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_gc_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_gc_float(struct, - fielddescr.ofs)) - else: - raise NotImplementedError + return llimpl.do_getfield_gc_int(struct, fielddescr.ofs) + def bh_getfield_gc_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_ptr(struct, fielddescr.ofs) + def bh_getfield_gc_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_float(struct, fielddescr.ofs) - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_raw_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_raw_float(struct, - fielddescr.ofs, - self.memo_cast)) - else: - raise NotImplementedError + return llimpl.do_getfield_raw_int(struct, fielddescr.ofs) + def bh_getfield_raw_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_ptr(struct, fielddescr.ofs) + def bh_getfield_raw_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_float(struct, fielddescr.ofs) - def do_new(self, size): - assert isinstance(size, Descr) - return history.BoxPtr(llimpl.do_new(size.ofs)) - - def do_new_with_vtable(self, vtablebox): - vtable = vtablebox.getint() - size = self.class_sizes[vtable] - result = llimpl.do_new(size.ofs) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, - vtable, self.memo_cast) - return history.BoxPtr(result) - - def do_new_array(self, countbox, size): - assert isinstance(size, Descr) - count = countbox.getint() - return history.BoxPtr(llimpl.do_new_array(size.ofs, count)) + def bh_new(self, sizedescr): + assert isinstance(sizedescr, Descr) + return llimpl.do_new(sizedescr.ofs) + + def bh_new_with_vtable(self, sizedescr, vtable): + assert isinstance(sizedescr, Descr) + result = llimpl.do_new(sizedescr.ofs) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, vtable) + return result + + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_new_array(self, arraydescr, length): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) - elif arraydescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setarrayitem_gc_int(array, index, newvalue, - self.memo_cast) - elif arraydescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setarrayitem_gc_float(array, index, newvalue) - else: - raise NotImplementedError + return llimpl.do_new_array(arraydescr.ofs, length) + + def bh_arraylen_gc(self, arraydescr, array): + assert isinstance(arraydescr, Descr) + return llimpl.do_arraylen_gc(arraydescr, array) + + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_int(array, index, newvalue) + + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_float(array, index, newvalue) - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - else: - raise NotImplementedError + llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memo_cast) - else: - raise NotImplementedError + llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue) - def do_same_as(self, box1): - return box1.clonebox() + def bh_newstr(self, length): + return llimpl.do_newstr(length) - def do_newstr(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newstr(0, length)) - - def do_newunicode(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newunicode(0, length)) - - def do_strsetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_strsetitem(0, string, index, newvalue) - - def do_unicodesetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_unicodesetitem(0, string, index, newvalue) + def bh_newunicode(self, length): + return llimpl.do_newunicode(length) - def do_call(self, args, calldescr): - assert isinstance(calldescr, Descr) - func = args[0].getint() - for arg in args[1:]: - if arg.type == REF: - llimpl.do_call_pushptr(arg.getref_base()) - elif arg.type == FLOAT: - llimpl.do_call_pushfloat(arg.getfloat()) - else: - llimpl.do_call_pushint(arg.getint()) - if calldescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) - elif calldescr.typeinfo == INT: - return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) - elif calldescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast)) - elif calldescr.typeinfo == 'v': # void - llimpl.do_call_void(func, self.memo_cast) - else: - raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + llimpl.do_strsetitem(string, index, newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + llimpl.do_unicodesetitem(string, index, newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(INT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_int(func) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(REF, calldescr, args_i, args_r, args_f) + return llimpl.do_call_ptr(func) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(FLOAT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_float(func) + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call('v', calldescr, args_i, args_r, args_f) + llimpl.do_call_void(func) - def do_cast_ptr_to_int(self, ptrbox): - return history.BoxInt(llimpl.cast_to_int(ptrbox.getref_base(), - self.memo_cast)) + def _prepare_call(self, resulttypeinfo, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, Descr) + assert calldescr.typeinfo == resulttypeinfo + if args_i is not None: + for x in args_i: + llimpl.do_call_pushint(x) + if args_r is not None: + for x in args_r: + llimpl.do_call_pushptr(x) + if args_f is not None: + for x in args_f: + llimpl.do_call_pushfloat(x) def force(self, force_token): - token = self.cast_int_to_adr(force_token) + token = llmemory.cast_int_to_adr(force_token) frame = llimpl.get_forced_token_frame(token) fail_index = llimpl.force(frame) self.latest_frame = frame return self.get_fail_descr_from_number(fail_index) -class OOtypeCPU(BaseCPU): +class OOtypeCPU_xxx_disabled(BaseCPU): is_oo = True ts = oohelper @@ -629,7 +546,7 @@ assert isinstance(typedescr, TypeDescr) return typedescr.getarraylength(box1) - def do_call(self, args, descr): + def do_call_XXX(self, args, descr): assert isinstance(descr, StaticMethDescr) funcbox = args[0] argboxes = args[1:] @@ -842,10 +759,3 @@ def __repr__(self): return '' % self.fieldname - - -# ____________________________________________________________ - -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(LLtypeCPU) -pypy.jit.metainterp.executor.make_execute_list(OOtypeCPU) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llgraph/test/test_llgraph.py Tue Jun 8 19:48:40 2010 @@ -7,6 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.test.runner_test import LLtypeBackendTest class TestLLTypeLLGraph(LLtypeBackendTest): @@ -18,25 +19,25 @@ def setup_method(self, _): self.cpu = self.cpu_type(None) - def test_cast_adr_to_int_and_back(self): - cpu = self.cpu - X = lltype.Struct('X', ('foo', lltype.Signed)) - x = lltype.malloc(X, immortal=True) - x.foo = 42 - a = llmemory.cast_ptr_to_adr(x) - i = cpu.cast_adr_to_int(a) - assert isinstance(i, int) - a2 = cpu.cast_int_to_adr(i) - assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x - assert cpu.cast_adr_to_int(llmemory.NULL) == 0 - assert cpu.cast_int_to_adr(0) == llmemory.NULL +def test_cast_adr_to_int_and_back(): + X = lltype.Struct('X', ('foo', lltype.Signed)) + x = lltype.malloc(X, immortal=True) + x.foo = 42 + a = llmemory.cast_ptr_to_adr(x) + i = heaptracker.adr2int(a) + assert lltype.typeOf(i) is lltype.Signed + a2 = heaptracker.int2adr(i) + assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x + assert heaptracker.adr2int(llmemory.NULL) == 0 + assert heaptracker.int2adr(0) == llmemory.NULL ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type def test_fielddescr_ootype(): + py.test.skip("ootype tests skipped") from pypy.rpython.ootypesystem import ootype from pypy.jit.backend.llgraph.runner import OOtypeCPU A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/descr.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/descr.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/descr.py Tue Jun 8 19:48:40 2010 @@ -1,10 +1,11 @@ import py -from pypy.rpython.lltypesystem import lltype, rffi, llmemory +from pypy.rpython.lltypesystem import lltype, rffi, llmemory, rclass from pypy.jit.backend.llsupport import symbolic, support from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # The point of the class organization in this file is to make instances # as compact as possible. This is done by not storing the field size or @@ -40,6 +41,10 @@ def repr_of_descr(self): return '' % self.size +class SizeDescrWithVTable(SizeDescr): + def as_vtable_size_descr(self): + return self + BaseSizeDescr = SizeDescr def get_size_descr(gccache, STRUCT): @@ -48,7 +53,10 @@ return cache[STRUCT] except KeyError: size = symbolic.get_size(STRUCT, gccache.translate_support_code) - sizedescr = SizeDescr(size) + if heaptracker.has_gcstruct_a_vtable(STRUCT): + sizedescr = SizeDescrWithVTable(size) + else: + sizedescr = SizeDescr(size) gccache.init_size_descr(STRUCT, sizedescr) cache[STRUCT] = sizedescr return sizedescr @@ -179,7 +187,6 @@ # CallDescrs class BaseCallDescr(AbstractDescr): - empty_box = BoxInt(0) _clsname = '' loop_token = None arg_classes = '' # <-- annotation hack @@ -191,35 +198,20 @@ def get_extra_info(self): return self.extrainfo - _returns_a_pointer = False # unless overridden by GcPtrCallDescr - _returns_a_float = False # unless overridden by FloatCallDescr - _returns_a_void = False # unless overridden by VoidCallDescr - - def returns_a_pointer(self): - return self._returns_a_pointer - - def returns_a_float(self): - return self._returns_a_float + def get_arg_types(self): + return self.arg_classes - def returns_a_void(self): - return self._returns_a_void + def get_return_type(self): + return self._return_type def get_result_size(self, translate_support_code): raise NotImplementedError - def get_call_stub(self): - return self.call_stub - def create_call_stub(self, rtyper, RESULT): - def process(no, c): - if c == 'i': - return 'args[%d].getint()' % (no,) - elif c == 'f': - return 'args[%d].getfloat()' % (no,) - elif c == 'r': - return 'args[%d].getref_base()' % (no,) - else: - raise Exception("Unknown type %s for type %s" % (c, TP)) + def process(c): + arg = 'args_%s[%d]' % (c, seen[c]) + seen[c] += 1 + return arg def TYPE(arg): if arg == 'i': @@ -230,21 +222,23 @@ return llmemory.GCREF elif arg == 'v': return lltype.Void - - args = ", ".join([process(i + 1, c) for i, c in - enumerate(self.arg_classes)]) - - if self.returns_a_pointer(): - result = 'history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, res))' - elif self.returns_a_float(): - result = 'history.BoxFloat(res)' - elif self.returns_a_void(): + + seen = {'i': 0, 'r': 0, 'f': 0} + args = ", ".join([process(c) for c in self.arg_classes]) + + if self.get_return_type() == history.INT: + result = 'rffi.cast(lltype.Signed, res)' + elif self.get_return_type() == history.REF: + result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)' + elif self.get_return_type() == history.FLOAT: + result = 'res' + elif self.get_return_type() == history.VOID: result = 'None' else: - result = 'history.BoxInt(rffi.cast(lltype.Signed, res))' + assert 0 source = py.code.Source(""" - def call_stub(args): - fnptr = rffi.cast(lltype.Ptr(FUNC), args[0].getint()) + def call_stub(func, args_i, args_r, args_f): + fnptr = rffi.cast(lltype.Ptr(FUNC), func) res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s) return %(result)s """ % locals()) @@ -255,35 +249,64 @@ exec source.compile() in d self.call_stub = d['call_stub'] + def verify_types(self, args_i, args_r, args_f, return_type): + assert self._return_type == return_type + assert self.arg_classes.count('i') == len(args_i or ()) + assert self.arg_classes.count('r') == len(args_r or ()) + assert self.arg_classes.count('f') == len(args_f or ()) + def repr_of_descr(self): return '<%s>' % self._clsname -class NonGcPtrCallDescr(BaseCallDescr): +class BaseIntCallDescr(BaseCallDescr): + # Base class of the various subclasses of descrs corresponding to + # calls having a return kind of 'int' (including non-gc pointers). + # The inheritance hierarchy is a bit different than with other Descr + # classes because of the 'call_stub' attribute, which is of type + # + # lambda func, args_i, args_r, args_f --> int/ref/float/void + # + # The purpose of BaseIntCallDescr is to be the parent of all classes + # in which 'call_stub' has a return kind of 'int'. + _return_type = history.INT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0) + +class NonGcPtrCallDescr(BaseIntCallDescr): _clsname = 'NonGcPtrCallDescr' - def get_result_size(self, translate_support_code): return symbolic.get_size_of_ptr(translate_support_code) -class GcPtrCallDescr(NonGcPtrCallDescr): - empty_box = BoxPtr(lltype.nullptr(llmemory.GCREF.TO)) +class GcPtrCallDescr(BaseCallDescr): _clsname = 'GcPtrCallDescr' - _returns_a_pointer = True + _return_type = history.REF + call_stub = staticmethod(lambda func, args_i, args_r, args_f: + lltype.nullptr(llmemory.GCREF.TO)) + def get_result_size(self, translate_support_code): + return symbolic.get_size_of_ptr(translate_support_code) + +class FloatCallDescr(BaseCallDescr): + _clsname = 'FloatCallDescr' + _return_type = history.FLOAT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0.0) + def get_result_size(self, translate_support_code): + return symbolic.get_size(lltype.Float, translate_support_code) -class VoidCallDescr(NonGcPtrCallDescr): - empty_box = None +class VoidCallDescr(BaseCallDescr): _clsname = 'VoidCallDescr' - _returns_a_void = True - + _return_type = history.VOID + call_stub = staticmethod(lambda func, args_i, args_r, args_f: None) def get_result_size(self, translate_support_code): return 0 def getCallDescrClass(RESULT): if RESULT is lltype.Void: return VoidCallDescr - return getDescrClass(RESULT, BaseCallDescr, GcPtrCallDescr, + if RESULT is lltype.Float: + return FloatCallDescr + return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr, NonGcPtrCallDescr, 'Call', 'get_result_size', - '_returns_a_float') + Ellipsis) # <= floatattrname should not be used here def get_call_descr(gccache, ARGS, RESULT, extrainfo=None): arg_classes = [] @@ -330,7 +353,6 @@ # if TYPE is lltype.Float: setattr(Descr, floatattrname, True) - Descr.empty_box = BoxFloat(0.0) # _cache[nameprefix, TYPE] = Descr return Descr Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/gc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/gc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/gc.py Tue Jun 8 19:48:40 2010 @@ -170,7 +170,7 @@ # first look in the hashtable, using an inexact hash (fails after # the object moves) addr = llmemory.cast_ptr_to_adr(gcref) - hash = llmemory.cast_adr_to_int(addr) + hash = llmemory.cast_adr_to_int(addr, "forced") hash -= hash >> self.HASHTABLE_BITS hash &= self.HASHTABLE_SIZE - 1 addr_ref = self.hashtable[hash] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/llmodel.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/llmodel.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/llmodel.py Tue Jun 8 19:48:40 2010 @@ -6,16 +6,19 @@ from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\ BoxFloat +from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.model import AbstractCPU 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, BaseSizeDescr from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr -from pypy.jit.backend.llsupport.descr import get_call_descr, BaseCallDescr +from pypy.jit.backend.llsupport.descr import get_call_descr +from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr +from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr from pypy.rpython.annlowlevel import cast_instance_to_base_ptr -empty_int_box = BoxInt(0) class AbstractLLCPU(AbstractCPU): from pypy.jit.metainterp.typesystem import llhelper as ts @@ -47,7 +50,7 @@ self._setup_exception_handling_translated() else: self._setup_exception_handling_untranslated() - self.clear_exception() + self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) self.setup() if translate_support_code: self._setup_on_leave_jitted_translated() @@ -57,9 +60,6 @@ def setup(self): pass - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case bk = self.rtyper.annotator.bookkeeper @@ -104,12 +104,10 @@ def save_exception(): # copy from _exception_emulator to the real attributes on self - tp_i = _exception_emulator[0] - v_i = _exception_emulator[1] + v_i = _exception_emulator[1] _exception_emulator[0] = 0 _exception_emulator[1] = 0 - self.saved_exception = tp_i - self.saved_exc_value = self._cast_int_to_gcref(v_i) + self.saved_exc_value = rffi.cast(llmemory.GCREF, v_i) self.pos_exception = pos_exception self.pos_exc_value = pos_exc_value @@ -120,15 +118,14 @@ def pos_exception(): addr = llop.get_exception_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def save_exception(): addr = llop.get_exception_addr(llmemory.Address) - exception = rffi.cast(lltype.Signed, addr.address[0]) addr.address[0] = llmemory.NULL addr = llop.get_exc_value_addr(llmemory.Address) exc_value = rffi.cast(llmemory.GCREF, addr.address[0]) @@ -136,7 +133,6 @@ # from now on, the state is again consistent -- no more RPython # exception is set. The following code produces a write barrier # in the assignment to self.saved_exc_value, as needed. - self.saved_exception = exception self.saved_exc_value = exc_value self.pos_exception = pos_exception @@ -174,16 +170,10 @@ f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc) return rffi.cast(lltype.Signed, f) - def get_exception(self): - return self.saved_exception - - def get_exc_value(self): - return self.saved_exc_value - - def clear_exception(self): - self.saved_exception = 0 + def grab_exc_value(self): + exc = self.saved_exc_value self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) - + return exc # ------------------- helpers and descriptions -------------------- @@ -213,24 +203,30 @@ def unpack_fielddescr(self, fielddescr): assert isinstance(fielddescr, BaseFieldDescr) + return fielddescr.offset + unpack_fielddescr._always_inline_ = True + + def unpack_fielddescr_size(self, fielddescr): + assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset size = fielddescr.get_field_size(self.translate_support_code) - ptr = fielddescr.is_pointer_field() - float = fielddescr.is_float_field() - return ofs, size, ptr, float - unpack_fielddescr._always_inline_ = True + return ofs, size + unpack_fielddescr_size._always_inline_ = True def arraydescrof(self, A): return get_array_descr(self.gc_ll_descr, A) def unpack_arraydescr(self, arraydescr): assert isinstance(arraydescr, BaseArrayDescr) + return arraydescr.get_base_size(self.translate_support_code) + unpack_arraydescr._always_inline_ = True + + def unpack_arraydescr_size(self, arraydescr): + assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_base_size(self.translate_support_code) size = arraydescr.get_item_size(self.translate_support_code) - ptr = arraydescr.is_array_of_pointers() - float = arraydescr.is_array_of_floats() - return ofs, size, ptr, float - unpack_arraydescr._always_inline_ = True + return ofs, size + unpack_arraydescr_size._always_inline_ = True def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo) @@ -249,254 +245,222 @@ # ____________________________________________________________ - def do_arraylen_gc(self, arraybox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_ofs_length(self.translate_support_code) - gcref = arraybox.getref_base() - length = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] - return BoxInt(length) - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) + return rffi.cast(rffi.CArrayPtr(lltype.Signed), array)[ofs/WORD] + + def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex): + ofs, size = self.unpack_arraydescr_size(arraydescr) # --- start of GC unsafe code (no GC operation!) --- items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - pval = self._cast_int_to_gcref(items[itemindex]) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - fval = items[itemindex] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: items = rffi.cast(rffi.CArrayPtr(TYPE), items) val = items[itemindex] # --- end of GC unsafe code --- - return BoxInt(rffi.cast(lltype.Signed, val)) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_setarrayitem_gc(self, arraybox, indexbox, vbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) - # - if ptr: - vboxptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, vboxptr) - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - items[itemindex] = self.cast_gcref_to_int(vboxptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - items[itemindex] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def bh_getarrayitem_gc_r(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + pval = self._cast_int_to_gcref(items[itemindex]) + # --- end of GC unsafe code --- + return pval + + def bh_getarrayitem_gc_f(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + fval = items[itemindex] + # --- end of GC unsafe code --- + return fval + + def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue): + ofs, size = self.unpack_arraydescr_size(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) items = rffi.cast(rffi.CArrayPtr(TYPE), items) - items[itemindex] = rffi.cast(TYPE, val) + items[itemindex] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def _new_do_len(TP): - def do_strlen(self, stringbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(TP, - self.translate_support_code) - gcref = stringbox.getref_base() - v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] - return BoxInt(v) - return do_strlen - - do_strlen = _new_do_len(rstr.STR) - do_unicodelen = _new_do_len(rstr.UNICODE) - - def do_strgetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] - return BoxInt(ord(v)) - - def do_unicodegetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - basesize = basesize // itemsize - v = rffi.cast(rffi.CArrayPtr(lltype.UniChar), gcref)[basesize + i] - return BoxInt(ord(v)) + def bh_setarrayitem_gc_r(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + self.gc_ll_descr.do_write_barrier(gcref, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + items[itemindex] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- + + def bh_setarrayitem_gc_f(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + items[itemindex] = newvalue + # --- end of GC unsafe code --- + + def bh_strlen(self, string): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return len(s.chars) + + def bh_unicodelen(self, string): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return len(u.chars) + + def bh_strgetitem(self, string, index): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return ord(s.chars[index]) + + def bh_unicodegetitem(self, string, index): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return ord(u.chars[index]) @specialize.argtype(1) - def _base_do_getfield(self, gcref, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) + def _base_do_getfield_i(self, struct, fielddescr): + ofs, size = self.unpack_fielddescr_size(fielddescr) # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), field)[0] - pval = self._cast_int_to_gcref(pval) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - fval = rffi.cast(rffi.CArrayPtr(lltype.Float), field)[0] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - val = rffi.cast(rffi.CArrayPtr(TYPE), field)[0] + val = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)[0] # --- end of GC unsafe code --- - val = rffi.cast(lltype.Signed, val) - return BoxInt(val) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_getfield_gc(self, structbox, fielddescr): - gcref = structbox.getref_base() - return self._base_do_getfield(gcref, fielddescr) + @specialize.argtype(1) + def _base_do_getfield_r(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0] + pval = self._cast_int_to_gcref(pval) + # --- end of GC unsafe code --- + return pval - def do_getfield_raw(self, structbox, fielddescr): - return self._base_do_getfield(structbox.getint(), fielddescr) + @specialize.argtype(1) + def _base_do_getfield_f(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fval = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr)[0] + # --- end of GC unsafe code --- + return fval + + bh_getfield_gc_i = _base_do_getfield_i + bh_getfield_gc_r = _base_do_getfield_r + bh_getfield_gc_f = _base_do_getfield_f + bh_getfield_raw_i = _base_do_getfield_i + bh_getfield_raw_r = _base_do_getfield_r + bh_getfield_raw_f = _base_do_getfield_f @specialize.argtype(1) - def _base_do_setfield(self, gcref, vbox, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) - # - if ptr: - assert lltype.typeOf(gcref) is not lltype.Signed, ( - "can't handle write barriers for setfield_raw") - ptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, ptr) - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Signed), field) - field[0] = self.cast_gcref_to_int(ptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Float), field) - field[0] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def _base_do_setfield_i(self, struct, fielddescr, newvalue): + ofs, size = self.unpack_fielddescr_size(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(TYPE), field) - field[0] = rffi.cast(TYPE, val) + fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr) + fieldptr[0] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def do_setfield_gc(self, structbox, vbox, fielddescr): - gcref = structbox.getref_base() - self._base_do_setfield(gcref, vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_r(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + assert lltype.typeOf(struct) is not lltype.Signed, ( + "can't handle write barriers for setfield_raw") + self.gc_ll_descr.do_write_barrier(struct, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr) + fieldptr[0] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- - def do_setfield_raw(self, structbox, vbox, fielddescr): - self._base_do_setfield(structbox.getint(), vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_f(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr) + fieldptr[0] = newvalue + # --- end of GC unsafe code --- + + bh_setfield_gc_i = _base_do_setfield_i + bh_setfield_gc_r = _base_do_setfield_r + bh_setfield_gc_f = _base_do_setfield_f + bh_setfield_raw_i = _base_do_setfield_i + bh_setfield_raw_r = _base_do_setfield_r + bh_setfield_raw_f = _base_do_setfield_f - def do_new(self, sizedescr): - res = self.gc_ll_descr.gc_malloc(sizedescr) - return BoxPtr(res) + def bh_new(self, sizedescr): + return self.gc_ll_descr.gc_malloc(sizedescr) - def do_new_with_vtable(self, classbox): - classint = classbox.getint() - descrsize = self.class_sizes[classint] - res = self.gc_ll_descr.gc_malloc(descrsize) + def bh_new_with_vtable(self, sizedescr, vtable): + res = self.gc_ll_descr.gc_malloc(sizedescr) if self.vtable_offset is not None: as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res) - as_array[self.vtable_offset/WORD] = classint - return BoxPtr(res) + as_array[self.vtable_offset/WORD] = vtable + return res - def do_new_array(self, countbox, arraydescr): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem) - return BoxPtr(res) - - def do_newstr(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_str(num_elem) - return BoxPtr(res) - - def do_newunicode(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_unicode(num_elem) - return BoxPtr(res) - - def do_strsetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) - - def do_unicodesetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - basesize = basesize // itemsize - rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v) - - def do_call(self, args, calldescr): - assert isinstance(calldescr, BaseCallDescr) - assert len(args) == 1 + len(calldescr.arg_classes) + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) + + def bh_new_array(self, arraydescr, length): + return self.gc_ll_descr.gc_malloc_array(arraydescr, length) + + def bh_newstr(self, length): + return self.gc_ll_descr.gc_malloc_str(length) + + def bh_newunicode(self, length): + return self.gc_ll_descr.gc_malloc_unicode(length) + + def bh_strsetitem(self, string, index, newvalue): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + s.chars[index] = chr(newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + u.chars[index] = unichr(newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, BaseIntCallDescr) if not we_are_translated(): - assert (list(calldescr.arg_classes) == - [arg.type for arg in args[1:]]) - callstub = calldescr.get_call_stub() - try: - return callstub(args) - except Exception, e: - if not we_are_translated(): - if not type(e) is LLException: - raise - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - e.args[1]) - self.saved_exception = rffi.cast(lltype.Signed, e.args[0]) - else: - ptr = cast_instance_to_base_ptr(e) - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - ptr) - self.saved_exception = rffi.cast(lltype.Signed, ptr.typeptr) - return calldescr.empty_box - - def do_cast_ptr_to_int(self, ptrbox): - return BoxInt(self.cast_gcref_to_int(ptrbox.getref_base())) + calldescr.verify_types(args_i, args_r, args_f, history.INT) + return calldescr.call_stub(func, args_i, args_r, args_f) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, GcPtrCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.REF) + return calldescr.call_stub(func, args_i, args_r, args_f) -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, FloatCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.FLOAT) + return calldescr.call_stub(func, args_i, args_r, args_f) + + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, VoidCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.VOID) + return calldescr.call_stub(func, args_i, args_r, args_f) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_descr.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_descr.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_descr.py Tue Jun 8 19:48:40 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp import history def test_get_size_descr(): c0 = GcCache(False) @@ -145,33 +146,29 @@ c0 = GcCache(False) descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char) assert descr1.get_result_size(False) == rffi.sizeof(lltype.Char) - assert not descr1.returns_a_pointer() - assert not descr1.returns_a_float() + assert descr1.get_return_type() == history.INT assert descr1.arg_classes == "ii" - assert isinstance(descr1.empty_box, BoxInt) # T = lltype.GcStruct('T') descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T)) assert descr2.get_result_size(False) == rffi.sizeof(lltype.Ptr(T)) - assert descr2.returns_a_pointer() - assert not descr2.returns_a_float() + assert descr2.get_return_type() == history.REF assert descr2.arg_classes == "r" - assert isinstance(descr2.empty_box, BoxPtr) # U = lltype.GcStruct('U', ('x', lltype.Signed)) assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U)) # V = lltype.Struct('V', ('x', lltype.Signed)) - assert isinstance(get_call_descr(c0, [], lltype.Ptr(V)).empty_box, BoxInt) + assert (get_call_descr(c0, [], lltype.Ptr(V)).get_return_type() == + history.INT) # - assert get_call_descr(c0, [], lltype.Void).empty_box is None + assert (get_call_descr(c0, [], lltype.Void).get_return_type() == + history.VOID) # descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float) assert descr4.get_result_size(False) == rffi.sizeof(lltype.Float) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" - assert isinstance(descr4.empty_box, BoxFloat) def test_get_call_descr_translated(): c1 = GcCache(True) @@ -179,14 +176,12 @@ U = lltype.GcStruct('U', ('x', lltype.Signed)) descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U)) assert isinstance(descr3.get_result_size(True), Symbolic) - assert descr3.returns_a_pointer() - assert not descr3.returns_a_float() + assert descr3.get_return_type() == history.REF assert descr3.arg_classes == "r" # descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float) assert isinstance(descr4.get_result_size(True), Symbolic) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" def test_call_descr_extra_info(): @@ -245,12 +240,11 @@ def f(a, b): return 'c' - call_stub = descr1.get_call_stub() + call_stub = descr1.call_stub fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) - res = call_stub([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxInt(1), BoxInt(2)]) - assert res.getint() == ord('c') + res = call_stub(rffi.cast(lltype.Signed, fnptr), [1, 2], None, None) + assert res == ord('c') ARRAY = lltype.GcArray(lltype.Signed) ARGS = [lltype.Float, lltype.Ptr(ARRAY)] @@ -264,6 +258,6 @@ a = lltype.malloc(ARRAY, 3) opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a) a[0] = 1 - res = descr2.get_call_stub()([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxFloat(3.5), BoxPtr(opaquea)]) - assert res.getfloat() == 4.5 + res = descr2.call_stub(rffi.cast(lltype.Signed, fnptr), + [], [opaquea], [3.5]) + assert res == 4.5 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_gc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_gc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/llsupport/test/test_gc.py Tue Jun 8 19:48:40 2010 @@ -291,7 +291,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -303,7 +303,7 @@ assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) - assert operations[1].opnum == rop.OOIS + assert operations[1].opnum == rop.PTR_EQ assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result @@ -324,7 +324,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -336,7 +336,7 @@ finally: rgc.can_move = old_can_move assert len(operations) == 1 - assert operations[0].opnum == rop.OOIS + assert operations[0].opnum == rop.PTR_EQ assert operations[0].args == [v_random_box, ConstPtr(s_gcref)] assert operations[0].result == v_result # check that s_gcref gets added to the list anyway, to make sure Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/model.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/model.py Tue Jun 8 19:48:40 2010 @@ -3,6 +3,7 @@ class AbstractCPU(object): supports_floats = False + _got_exception = None # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None @@ -24,9 +25,6 @@ def get_fail_descr_from_number(self, n): return self.fail_descr_list[n] - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def setup_once(self): """Called once by the front-end when the program starts.""" pass @@ -87,30 +85,27 @@ or from 'args' if it was a FINISH). Returns a ptr or an obj.""" raise NotImplementedError + def get_latest_value_count(self): + """Return how many values are ready to be returned by + get_latest_value_xxx(). Only after a guard failure; not + necessarily correct after a FINISH.""" + raise NotImplementedError + def get_latest_force_token(self): """After a GUARD_NOT_FORCED fails, this function returns the same FORCE_TOKEN result as the one in the just-failed loop.""" raise NotImplementedError - def make_boxes_from_latest_value(self, faildescr): - """Build a list of Boxes (and None for holes) that contains - the current values, as would be returned by calls to - get_latest_value_xxx().""" - raise NotImplementedError - - def get_exception(self): - raise NotImplementedError - - def get_exc_value(self): - raise NotImplementedError - - def clear_exception(self): - raise NotImplementedError - - def get_overflow_error(self): + def clear_latest_values(self, count): + """Clear the latest values (at least the ref ones), so that + they no longer keep objects alive. 'count' is the number of + values -- normally get_latest_value_count().""" raise NotImplementedError - def get_zero_division_error(self): + def grab_exc_value(self): + """Return and clear the exception set by the latest execute_token(), + when it exits due to a failure of a GUARD_EXCEPTION or + GUARD_NO_EXCEPTION. (Returns a GCREF)""" # XXX remove me raise NotImplementedError @staticmethod @@ -118,10 +113,6 @@ raise NotImplementedError @staticmethod - def numof(S): - raise NotImplementedError - - @staticmethod def fielddescrof(S, fieldname): """Return the Descr corresponding to field 'fieldname' on the structure 'S'. It is important that this function (at least) @@ -157,101 +148,87 @@ # lltype specific operations # -------------------------- - - def do_arraylen_gc(self, arraybox, arraydescr): - raise NotImplementedError - def do_strlen(self, stringbox): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): raise NotImplementedError - - def do_strgetitem(self, stringbox, indexbox): + def bh_getarrayitem_gc_r(self, arraydescr, array, index): raise NotImplementedError - - def do_unicodelen(self, stringbox): + def bh_getarrayitem_gc_f(self, arraydescr, array, index): raise NotImplementedError - def do_unicodegetitem(self, stringbox, indexbox): + def bh_getfield_gc_i(self, struct, fielddescr): raise NotImplementedError - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getfield_gc_r(self, struct, fielddescr): + raise NotImplementedError + def bh_getfield_gc_f(self, struct, fielddescr): raise NotImplementedError - def do_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): - return self.do_call([fnptr, sourcebox, destbox, source_startbox, - dest_startbox, lengthbox], calldescr) - - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): raise NotImplementedError - - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_r(self, struct, fielddescr): raise NotImplementedError - - def do_new(self, sizedescr): + def bh_getfield_raw_f(self, struct, fielddescr): raise NotImplementedError - def do_new_with_vtable(self, classbox): + def bh_new(self, sizedescr): + raise NotImplementedError + def bh_new_with_vtable(self, sizedescr, vtable): raise NotImplementedError - - def do_new_array(self, lengthbox, arraydescr): + def bh_new_array(self, arraydescr, length): raise NotImplementedError - - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_newstr(self, length): + raise NotImplementedError + def bh_newunicode(self, length): raise NotImplementedError - def do_setarrayitem_raw(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): raise NotImplementedError - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_classof(self, struct): raise NotImplementedError - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newstr(self, lengthbox): + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newunicode(self, lengthbox): + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): raise NotImplementedError - def do_strsetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_unicodesetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call(self, args, calldescr): + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_assembler(self, args, token): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call_loopinvariant(self, args, calldescr): - return self.do_call(args, calldescr) - - def do_cond_call_gc_wb(self, args, calldescr): + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_cast_ptr_to_int(self, ptrbox): + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_may_force(self, args, calldescr): - return self.do_call(args, calldescr) - - def force(self, force_token): + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - # ootype specific operations - # -------------------------- - - def do_runtimenew(self, classbox): + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - def do_oosend(self, args, descr): + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + raise NotImplementedError + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - def do_instanceof(self, instancebox, typedescr): + def bh_strlen(self, string): + raise NotImplementedError + def bh_strgetitem(self, string, index): + raise NotImplementedError + def bh_unicodelen(self, string): + raise NotImplementedError + def bh_unicodegetitem(self, string, index): + raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + raise NotImplementedError + def bh_unicodesetitem(self, string, index, newvalue): raise NotImplementedError - def typedescr2classbox(self, descr): + def force(self, force_token): raise NotImplementedError Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/runner_test.py Tue Jun 8 19:48:40 2010 @@ -13,6 +13,8 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException +from pypy.jit.codewriter import heaptracker + class Runner(object): @@ -236,7 +238,7 @@ res = self.cpu.get_latest_value_int(0) assert res == 20 - def test_make_boxes_from_latest_values(self): + def test_get_latest_value_count(self): i0 = BoxInt() i1 = BoxInt() i2 = BoxInt() @@ -255,12 +257,12 @@ self.cpu.set_future_value_int(0, 2) fail = self.cpu.execute_token(looptoken) assert fail is faildescr1 - boxes = self.cpu.make_boxes_from_latest_values(faildescr1) - assert len(boxes) == 3 - assert boxes[0] is None - assert isinstance(boxes[1], BoxInt) - assert boxes[1].value == 10 - assert boxes[2] is None + + count = self.cpu.get_latest_value_count() + assert count == 3 + assert self.cpu.get_latest_value_int(1) == 10 + assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok + self.cpu.clear_latest_values(3) def test_finish(self): i0 = BoxInt() @@ -375,8 +377,8 @@ looptoken = LoopToken() self.cpu.compile_loop([v1, v2], ops, looptoken) for x, y, z in testcases: - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) fail = self.cpu.execute_token(looptoken) @@ -386,13 +388,13 @@ assert fail.identifier == 2 if z != boom: assert self.cpu.get_latest_value_int(0) == z - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_ovf_operations_reversed(self): self.test_ovf_operations(reversed=True) - def test_do_call(self): + def test_bh_call(self): cpu = self.cpu # def func(c): @@ -400,24 +402,21 @@ FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxInt(ord('A'))], - calldescr) - assert x.value == ord('B') + x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value, + calldescr, [ord('A')], None, None) + assert x == ord('B') if cpu.supports_floats: def func(f, i): - return float(i) + f + return f - float(i) FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed], lltype.Float)) func_ptr = llhelper(FPTR, func) FTP = deref(FPTR) calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxFloat(3.5), BoxInt(42)], - calldescr) - assert x.value == 42 + 3.5 + x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value, + calldescr, + [42], None, [3.5]) + assert x == 3.5 - 42 def test_call(self): @@ -611,31 +610,31 @@ def test_ooops(self): u1_box, U_box = self.alloc_instance(self.U) u2_box, U_box = self.alloc_instance(self.U) - r = self.execute_operation(rop.OOIS, [u1_box, - u1_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, + u1_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [u2_box, - u2_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, + u2_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [u1_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int') assert r.value == 1 # null_box = self.null_instance() - r = self.execute_operation(rop.OOIS, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, + null_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOIS, [u1_box, null_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [null_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, + null_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, null_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [null_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int') assert r.value == 1 def test_array_basic(self): @@ -768,10 +767,10 @@ assert r.value == 153 def test_do_unicode_basic(self): - u_box = self.cpu.do_newunicode(ConstInt(5)) - self.cpu.do_unicodesetitem(u_box, BoxInt(4), BoxInt(123)) - r = self.cpu.do_unicodegetitem(u_box, BoxInt(4)) - assert r.value == 123 + u = self.cpu.bh_newunicode(5) + self.cpu.bh_unicodesetitem(u, 4, 123) + r = self.cpu.bh_unicodegetitem(u, 4) + assert r == 123 def test_unicode_basic(self): u_box = self.alloc_unicode(u"hello\u1234") @@ -808,17 +807,10 @@ assert r.value == 5.5 def test_virtual_ref(self): - # if VIRTUAL_REF reaches the backend, it should just be a SAME_AS - u_box = self.alloc_unicode(u"hello\u1234") - r = self.execute_operation(rop.VIRTUAL_REF, [u_box, ConstInt(2)], - 'ref') - assert r.value == u_box.value + pass # VIRTUAL_REF must not reach the backend nowadays def test_virtual_ref_finish(self): - # if VIRTUAL_REF_FINISH reaches the backend, it is a no-op - self.execute_operation(rop.VIRTUAL_REF_FINISH, - [BoxInt(123), BoxInt(234)], - 'void') + pass # VIRTUAL_REF_FINISH must not reach the backend nowadays def test_jump(self): # this test generates small loops where the JUMP passes many @@ -1082,7 +1074,6 @@ operator.truediv, no_zero_divison yield nan_and_infinity, rop.FLOAT_NEG, operator.neg, all_cases_unary yield nan_and_infinity, rop.FLOAT_ABS, abs, all_cases_unary - yield nan_and_infinity, rop.FLOAT_IS_TRUE, bool, all_cases_unary yield nan_and_infinity, rop.FLOAT_LT, operator.lt, all_cases_binary yield nan_and_infinity, rop.FLOAT_LE, operator.le, all_cases_binary yield nan_and_infinity, rop.FLOAT_EQ, operator.eq, all_cases_binary @@ -1102,7 +1093,7 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): addr = llmemory.cast_ptr_to_adr(func_ptr) - return BoxInt(cpu.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) MY_VTABLE = rclass.OBJECT_VTABLE # for tests only @@ -1134,7 +1125,7 @@ elif T == self.U: t.parent.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) + T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr)) return t_box, T_box def null_instance(self): @@ -1163,23 +1154,26 @@ def test_casts(self): + py.test.skip("xxx fix or kill") from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') x = lltype.malloc(TP) x = lltype.cast_opaque_ptr(llmemory.GCREF, x) res = self.execute_operation(rop.CAST_PTR_TO_INT, [BoxPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) res = self.execute_operation(rop.CAST_PTR_TO_INT, [ConstPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) - r = self.execute_operation(rop.OOIS, [BoxInt(v), BoxInt(v)], 'int') + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) + r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [BoxInt(v), BoxInt(v)], 'int') + r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 0 lltype.free(x, flavor='raw') @@ -1206,7 +1200,7 @@ S = lltype.Struct('S', ('x', lltype.Signed)) s = lltype.malloc(S, flavor='raw') sa = llmemory.cast_ptr_to_adr(s) - s_box = BoxInt(self.cpu.cast_adr_to_int(sa)) + s_box = BoxInt(heaptracker.adr2int(sa)) for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW), (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)): fd = self.cpu.fielddescrof(S, 'x') @@ -1218,7 +1212,9 @@ def test_new_with_vtable(self): cpu = self.cpu t_box, T_box = self.alloc_instance(self.T) - cpu.set_class_sizes({T_box.value: cpu.sizeof(self.T)}) + vtable = llmemory.cast_adr_to_ptr( + llmemory.cast_int_to_adr(T_box.value), heaptracker.VTABLETYPE) + heaptracker.register_known_gctype(cpu, vtable, self.T) r1 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') r2 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') assert r1.value != r2.value @@ -1234,11 +1230,11 @@ s = lltype.cast_opaque_ptr(lltype.Ptr(self.T), r1.value) assert s.parent.chr1 == chr(190) assert s.parent.chr2 == chr(150) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1313 - self.cpu.do_setfield_gc(r1, BoxInt(1333), descrshort) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1333 + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1313 + self.cpu.bh_setfield_gc_i(r1.value, descrshort, 1333) + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1333 r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int', descr=descrshort) assert r.value == 1333 @@ -1305,11 +1301,13 @@ self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 assert self.cpu.get_latest_value_ref(1) == xptr - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) ytp.subclassrange_min = 2 @@ -1327,7 +1325,9 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == yptr + assert not self.cpu.grab_exc_value() # cleared exc_tp = xtp exc_ptr = xptr @@ -1343,11 +1343,13 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == xptr self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_cond_call_gc_wb(self): def func_void(a, b): @@ -1524,108 +1526,92 @@ A = lltype.GcArray(lltype.Char) descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) - x = cpu.do_arraylen_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), - descr_A) - assert x.value == 5 + x = cpu.bh_arraylen_gc(descr_A, + lltype.cast_opaque_ptr(llmemory.GCREF, a)) + assert x == 5 # a[2] = 'Y' - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2), - descr_A) - assert x.value == ord('Y') + x = cpu.bh_getarrayitem_gc_i( + descr_A, lltype.cast_opaque_ptr(llmemory.GCREF, a), 2) + assert x == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3), - descr_B) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 3) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a if self.cpu.supports_floats: C = lltype.GcArray(lltype.Float) c = lltype.malloc(C, 6) c[3] = 3.5 descr_C = cpu.arraydescrof(C) - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(3), - descr_C) - assert isinstance(x, BoxFloat) - assert x.getfloat() == 3.5 - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(4), - BoxFloat(4.5), descr_C) + x = cpu.bh_getarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 3) + assert x == 3.5 + cpu.bh_setarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 4, 4.5) assert c[4] == 4.5 s = rstr.mallocstr(6) - x = cpu.do_strlen( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))) - assert x.value == 6 + x = cpu.bh_strlen(lltype.cast_opaque_ptr(llmemory.GCREF, s)) + assert x == 6 # s.chars[3] = 'X' - x = cpu.do_strgetitem( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)) - assert x.value == ord('X') + x = cpu.bh_strgetitem(lltype.cast_opaque_ptr(llmemory.GCREF, s), 3) + assert x == ord('X') # S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A)), ('z', lltype.Float)) descrfld_x = cpu.fielddescrof(S, 'x') s = lltype.malloc(S) s.x = 'Z' - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_x) - assert x.value == ord('Z') - # - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(ord('4')), - descrfld_x) + x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x) + assert x == ord('Z') + # + cpu.bh_setfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x, + ord('4')) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_y) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a # s.y = lltype.nullptr(A) - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x, - descrfld_y) + cpu.bh_setfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y, x) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char)) #, ('y', lltype.Ptr(A))) descrfld_rx = cpu.fielddescrof(RS, 'x') rs = lltype.malloc(RS, immortal=True) rs.x = '?' - x = cpu.do_getfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + x = cpu.bh_getfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx) - assert x.value == ord('?') + assert x == ord('?') # - cpu.do_setfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(ord('!')), - descrfld_rx) + cpu.bh_setfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), + descrfld_rx, ord('!')) assert rs.x == '!' # if self.cpu.supports_floats: descrfld_z = cpu.fielddescrof(S, 'z') - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxFloat(3.5), - descrfld_z) + cpu.bh_setfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_z, 3.5) assert s.z == 3.5 s.z = 3.2 - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + x = cpu.bh_getfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), descrfld_z) - assert x.getfloat() == 3.2 + assert x == 3.2 ### we don't support in the JIT for now GC pointers ### stored inside non-GC structs. #descrfld_ry = cpu.fielddescrof(RS, 'y') @@ -1643,45 +1629,43 @@ #assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new(descrsize) - assert isinstance(x, BoxPtr) - x.getref(lltype.Ptr(S)) + x = cpu.bh_new(descrsize) + lltype.cast_opaque_ptr(lltype.Ptr(S), x) # type check # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - vtable2_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)) - cpu.set_class_sizes({vtable2_int: descrsize2}) - x = cpu.do_new_with_vtable(ConstInt(vtable2_int)) - assert isinstance(x, BoxPtr) + vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2)) + heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT) + x = cpu.bh_new_with_vtable(descrsize2, vtable2_int) + lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check # well... #assert x.getref(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array(BoxInt(7), arraydescr) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(A))) == 7 - # - cpu.do_setarrayitem_gc( - x, BoxInt(5), BoxInt(ord('*')), descr_A) - assert x.getref(lltype.Ptr(A))[5] == '*' - # - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), - BoxInt(1), x, - descr_B) - assert b[1] == x.getref(lltype.Ptr(A)) - # - x = cpu.do_newstr(BoxInt(5)) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(rstr.STR)).chars) == 5 - # - cpu.do_strsetitem(x, BoxInt(4), BoxInt(ord('/'))) - assert x.getref(lltype.Ptr(rstr.STR)).chars[4] == '/' - # - x = cpu.do_newstr(BoxInt(5)) - y = cpu.do_cast_ptr_to_int(x) - assert isinstance(y, BoxInt) - assert y.value == cpu.cast_gcref_to_int(x.value) + x = cpu.bh_new_array(arraydescr, 7) + array = lltype.cast_opaque_ptr(lltype.Ptr(A), x) + assert len(array) == 7 + # + cpu.bh_setarrayitem_gc_i(descr_A, x, 5, ord('*')) + assert array[5] == '*' + # + cpu.bh_setarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 1, x) + assert b[1] == array + # + x = cpu.bh_newstr(5) + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), x) + assert len(str.chars) == 5 + # + cpu.bh_strsetitem(x, 4, ord('/')) + assert str.chars[4] == '/' + # +## x = cpu.bh_newstr(5) +## y = cpu.bh_cast_ptr_to_int(x) +## z = cpu.bh_cast_ptr_to_int(x) +## y = rffi.get_real_int(y) +## z = rffi.get_real_int(z) +## assert type(y) == type(z) == int and y == z def test_sorting_of_fields(self): S = self.S @@ -1694,7 +1678,7 @@ def test_guards_nongc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) vbox = BoxInt(v) ops = [ (rop.GUARD_NONNULL, vbox, False), @@ -1797,6 +1781,9 @@ malloc = staticmethod(ootype.new) nullptr = staticmethod(ootype.null) + def setup_class(cls): + py.test.skip("ootype tests skipped") + @classmethod def get_funcbox(cls, cpu, func_ptr): return BoxObj(ootype.cast_to_object(func_ptr)) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_ll_random.py Tue Jun 8 19:48:40 2010 @@ -3,8 +3,9 @@ from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr -from pypy.jit.metainterp.history import ConstAddr, BoxPtr, BoxInt +from pypy.jit.metainterp.history import BoxPtr, BoxInt from pypy.jit.metainterp.history import BasicFailDescr +from pypy.jit.codewriter import heaptracker from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask from pypy.rpython.llinterp import LLException @@ -19,13 +20,11 @@ self.runicodes = [] self.structure_types = [] self.structure_types_and_vtables = [] - self.class_sizes_cache = [] def fork(self, cpu, loop, vars): fork = test_random.OperationBuilder.fork(self, cpu, loop, vars) fork.structure_types = self.structure_types fork.structure_types_and_vtables = self.structure_types_and_vtables - fork.class_sizes_cache = self.class_sizes_cache return fork def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): @@ -107,11 +106,7 @@ vtable.name[len(name)] = '\x00' self.structure_types_and_vtables.append((S, vtable)) # - vtable_adr = llmemory.cast_ptr_to_adr(vtable) - vtable_int = self.cpu.cast_adr_to_int(vtable_adr) - descr = self.cpu.sizeof(S) - self.class_sizes_cache.append((vtable_int, descr)) - self.cpu.set_class_sizes(dict(self.class_sizes_cache)) + heaptracker.register_known_gctype(self.cpu, vtable, S) # return S, vtable @@ -186,6 +181,9 @@ # ____________________________________________________________ +def ConstAddr(addr, cpu): + return ConstInt(heaptracker.adr2int(addr)) + class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): ptrvars = [(v, S) for (v, S) in builder.ptrvars @@ -507,8 +505,6 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(), descr=BasicFailDescr()) op.fail_args = fail_subset @@ -525,8 +521,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(), descr=BasicFailDescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) @@ -546,8 +540,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/test/test_random.py Tue Jun 8 19:48:40 2010 @@ -4,7 +4,7 @@ from pypy.jit.backend.test import conftest as demo_conftest from pypy.jit.metainterp.history import BasicFailDescr, TreeLoop from pypy.jit.metainterp.history import BoxInt, ConstInt, LoopToken -from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat, Const from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute_nonspec @@ -17,9 +17,14 @@ def __init__(self, subops): self.operations = subops +class FakeMetaInterp(object): + def execute_raised(self, exc, constant=False): + self._got_exc = exc + class OperationBuilder(object): def __init__(self, cpu, loop, vars): self.cpu = cpu + self.fakemetainterp = FakeMetaInterp() self.loop = loop self.intvars = [box for box in vars if isinstance(box, BoxInt)] self.boolvars = [] # subset of self.intvars @@ -40,7 +45,9 @@ return fork def do(self, opnum, argboxes, descr=None): - v_result = execute_nonspec(self.cpu, opnum, argboxes, descr) + self.fakemetainterp._got_exc = None + v_result = execute_nonspec(self.cpu, self.fakemetainterp, + opnum, argboxes, descr) if isinstance(v_result, Const): v_result = v_result.clonebox() self.loop.operations.append(ResOperation(opnum, argboxes, v_result, @@ -56,11 +63,14 @@ if S == S2 and not (isinstance(v, ConstPtr) and isinstance(v2, ConstPtr)): if r.random() < 0.5: - return self.do(rop.OOIS, [v, v2]) + return self.do(rop.PTR_EQ, [v, v2]) else: - return self.do(rop.OOISNOT, [v, v2]) + return self.do(rop.PTR_NE, [v, v2]) v = r.choice(self.intvars) - return self.do(rop.INT_IS_TRUE, [v]) + if r.random() < 0.7: + return self.do(rop.INT_IS_TRUE, [v]) + else: + return self.do(rop.INT_IS_ZERO, [v]) def subset_of_intvars(self, r): subset = [] @@ -79,16 +89,16 @@ for v in op.args: if v in names: args.append(names[v]) - elif isinstance(v, ConstAddr): - try: - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - except AttributeError: - args.append('ConstAddr(...)') - else: - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) +## elif isinstance(v, ConstAddr): +## try: +## name = ''.join([v.value.ptr.name[i] +## for i in range(len(v.value.ptr.name)-1)]) +## except AttributeError: +## args.append('ConstAddr(...)') +## else: +## args.append( +## 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' +## % name) elif isinstance(v, ConstFloat): args.append('ConstFloat(%r)' % v.value) elif isinstance(v, ConstInt): @@ -264,8 +274,8 @@ fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) - if builder.cpu._overflow_flag: # overflow detected - del builder.cpu._overflow_flag + if builder.fakemetainterp._got_exc: # overflow detected + assert isinstance(builder.fakemetainterp._got_exc, OverflowError) op = ResOperation(rop.GUARD_OVERFLOW, [], None) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including @@ -413,7 +423,7 @@ OPERATIONS.append(UnaryOperation(_op)) OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) -OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True)) +OPERATIONS.append(UnaryOperation(rop.INT_IS_ZERO, boolres=True)) OPERATIONS.append(ConstUnaryOperation(rop.SAME_AS, boolres='sometimes')) for _op in [rop.INT_ADD_OVF, @@ -434,8 +444,6 @@ ]: OPERATIONS.append(UnaryFloatOperation(_op)) -OPERATIONS.append(UnaryFloatOperation(rop.FLOAT_IS_TRUE, boolres=True)) - OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT)) OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT)) @@ -587,8 +595,8 @@ def run_loop(self): cpu = self.builder.cpu self.clear_state() - assert not cpu.get_exception() - assert not cpu.get_exc_value() + exc = cpu.grab_exc_value() + assert not exc for i, box in enumerate(self.startvars): if isinstance(box, BoxInt): @@ -609,15 +617,13 @@ self.expected[v], i) ) + exc = cpu.grab_exc_value() if (self.guard_op is not None and self.guard_op.is_guard_exception()): if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: - assert cpu.get_exception() - assert cpu.get_exc_value() - cpu.clear_exception() + assert exc else: - assert not cpu.get_exception() - assert not cpu.get_exc_value() + assert not exc def build_bridge(self): def exc_handling(guard_op): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/assembler.py Tue Jun 8 19:48:40 2010 @@ -633,8 +633,8 @@ genop_int_ne = _cmpop("NE", "NE") genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") - genop_oois = genop_int_eq - genop_ooisnot = genop_int_ne + genop_ptr_eq = genop_int_eq + genop_ptr_ne = genop_int_ne genop_float_lt = _cmpop_float('B') genop_float_le = _cmpop_float('BE') @@ -654,8 +654,8 @@ genop_guard_int_ne = _cmpop_guard("NE", "NE", "E", "E") genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") - genop_guard_oois = genop_guard_int_eq - genop_guard_ooisnot = genop_guard_int_ne + genop_guard_ptr_eq = genop_guard_int_eq + genop_guard_ptr_ne = genop_guard_int_ne genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") @@ -689,32 +689,6 @@ # Following what gcc does: res = x & 0x7FFFFFFFFFFFFFFF self.mc.ANDPD(arglocs[0], self.loc_float_const_abs) - def genop_guard_float_is_true(self, op, guard_op, addr, arglocs, resloc): - guard_opnum = guard_op.opnum - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - mc = self.mc._mc - if guard_opnum == rop.GUARD_TRUE: - mc.JP(rel8(6)) - mc.JZ(rel32(addr)) - return mc.tell() - 4 - else: - mc.JP(rel8(2)) - mc.JZ(rel8(5)) - return self.implement_guard(addr, mc.JMP) - - def genop_float_is_true(self, op, arglocs, resloc): - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - rl = resloc.lowest8bits() - rh = resloc.higher8bits() - self.mc.SETNE(rl) - self.mc.SETP(rh) - self.mc.OR(rl, rh) - self.mc.MOVZX(resloc, rl) - def genop_cast_float_to_int(self, op, arglocs, resloc): self.mc.CVTTSD2SI(resloc, arglocs[0]) @@ -753,7 +727,7 @@ self.mc.SETNE(rl) self.mc.MOVZX(resloc, rl) - def genop_guard_bool_not(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_zero(self, op, guard_op, addr, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm8(0)) if guard_opnum == rop.GUARD_TRUE: @@ -761,13 +735,15 @@ else: return self.implement_guard(addr, self.mc.JZ) - def genop_bool_not(self, op, arglocs, resloc): - self.mc.XOR(arglocs[0], imm8(1)) + def genop_int_is_zero(self, op, arglocs, resloc): + self.mc.CMP(arglocs[0], imm8(0)) + rl = resloc.lowest8bits() + self.mc.SETE(rl) + self.mc.MOVZX(resloc, rl) def genop_same_as(self, op, arglocs, resloc): self.mov(arglocs[0], resloc) - genop_cast_ptr_to_int = genop_same_as - genop_virtual_ref = genop_same_as + #genop_cast_ptr_to_int = genop_same_as def genop_int_mod(self, op, arglocs, resloc): self.mc.CDQ() @@ -1115,13 +1091,8 @@ n = self.CODE_HOLE mc.writechr(n) mc.writechr(self.CODE_STOP) - # preallocate the fail_boxes - i = len(failargs) - 1 - if i >= 0: - self.fail_boxes_int.get_addr_for_num(i) - self.fail_boxes_ptr.get_addr_for_num(i) - if self.cpu.supports_floats: - self.fail_boxes_float.get_addr_for_num(i) + # assert that the fail_boxes lists are big enough + assert len(failargs) <= self.fail_boxes_int.SIZE def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager @@ -1165,39 +1136,6 @@ arglocs.append(loc) return arglocs[:] - def make_boxes_from_latest_values(self, bytecode): - bytecode = rffi.cast(rffi.UCHARP, bytecode) - boxes = [] - while 1: - # decode the next instruction from the bytecode - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - kind = code & 3 - while code > 0x7F: - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - index = len(boxes) - if kind == self.DESCR_INT: - box = BoxInt(self.fail_boxes_int.getitem(index)) - elif kind == self.DESCR_REF: - box = BoxPtr(self.fail_boxes_ptr.getitem(index)) - # clear after reading (xxx duplicates - # get_latest_value_ref()) - self.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - elif kind == self.DESCR_FLOAT: - box = BoxFloat(self.fail_boxes_float.getitem(index)) - else: - assert kind == self.DESCR_SPECIAL - if code == self.CODE_STOP: - break - elif code == self.CODE_HOLE: - box = None - else: - assert 0, "bad code" - boxes.append(box) - return boxes - @rgc.no_collect def grab_frame_values(self, bytecode, frame_addr, allregisters): # no malloc allowed here!! @@ -1258,6 +1196,7 @@ # if not we_are_translated(): assert bytecode[4] == 0xCC + self.fail_boxes_count = num fail_index = rffi.cast(rffi.LONGP, bytecode)[0] return fail_index Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/regalloc.py Tue Jun 8 19:48:40 2010 @@ -3,7 +3,7 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, ConstAddr, BoxPtr, + ResOperation, BoxPtr, LoopToken, INT, REF, FLOAT) from pypy.jit.backend.x86.ri386 import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr @@ -11,6 +11,7 @@ from pypy.rlib import rgc from pypy.jit.backend.llsupport import symbolic from pypy.jit.backend.x86.jump import remap_frame_layout +from pypy.jit.codewriter import heaptracker from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr @@ -45,8 +46,6 @@ print "convert_to_imm: ConstPtr needs special care" raise AssertionError return imm(rffi.cast(lltype.Signed, c.value)) - elif isinstance(c, ConstAddr): - return imm(ll2ctypes.cast_adr_to_int(c.value)) else: print "convert_to_imm: got a %s" % c raise AssertionError @@ -550,8 +549,8 @@ consider_uint_lt = _consider_compop consider_uint_le = _consider_compop consider_uint_ge = _consider_compop - consider_oois = _consider_compop - consider_ooisnot = _consider_compop + consider_ptr_eq = _consider_compop + consider_ptr_ne = _consider_compop def _consider_float_op(self, op): loc1 = self.xrm.loc(op.args[1]) @@ -593,20 +592,6 @@ self.Perform(op, [loc0], loc0) self.xrm.possibly_free_var(op.args[0]) - def consider_float_is_true(self, op, guard_op): - # doesn't need arg to be in a register - tmpbox0 = TempBox() - loc0 = self.xrm.force_allocate_reg(tmpbox0) - loc1 = self.xrm.loc(op.args[0]) - arglocs = [loc0, loc1] - self.xrm.possibly_free_var(op.args[0]) - self.xrm.possibly_free_var(tmpbox0) - if guard_op is not None: - self.perform_with_guard(op, guard_op, arglocs, None) - else: - loc2 = self.rm.force_allocate_reg(op.result, need_lower_byte=True) - self.Perform(op, arglocs, loc2) - def consider_cast_float_to_int(self, op): loc0 = self.xrm.make_sure_var_in_reg(op.args[0], imm_fine=False) loc1 = self.rm.force_allocate_reg(op.result) @@ -725,7 +710,7 @@ def consider_new_with_vtable(self, op): classint = op.args[0].getint() - descrsize = self.assembler.cpu.class_sizes[classint] + descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint) if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize): self._fastpath_malloc(op, descrsize) self.assembler.set_vtable(eax, imm(classint)) @@ -889,22 +874,14 @@ resloc = self.rm.force_allocate_reg(op.result, need_lower_byte=True) self.Perform(op, [argloc], resloc) - def consider_bool_not(self, op, guard_op): - if guard_op is not None: - # doesn't need arg to be in a register - argloc = self.loc(op.args[0]) - self.rm.possibly_free_var(op.args[0]) - self.perform_with_guard(op, guard_op, [argloc], None) - else: - self.consider_int_neg(op) + consider_int_is_zero = consider_int_is_true def consider_same_as(self, op): argloc = self.loc(op.args[0]) self.possibly_free_var(op.args[0]) resloc = self.force_allocate_reg(op.result) self.Perform(op, [argloc], resloc) - consider_cast_ptr_to_int = consider_same_as - consider_virtual_ref = consider_same_as + #consider_cast_ptr_to_int = consider_same_as def consider_strlen(self, op): base_loc = self.rm.make_sure_var_in_reg(op.args[0], op.args) @@ -963,9 +940,6 @@ def consider_debug_merge_point(self, op): pass - def consider_virtual_ref_finish(self, op): - self.possibly_free_vars(op.args) - def get_mark_gc_roots(self, gcrootmap): shape = gcrootmap.get_basic_shape() for v, val in self.fm.frame_bindings.items(): @@ -973,6 +947,8 @@ assert isinstance(val, MODRM) gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position)) for v, reg in self.rm.reg_bindings.items(): + if reg is eax: + continue # ok to ignore this one if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)): if reg is ebx: gcrootmap.add_ebx(shape) @@ -981,7 +957,8 @@ elif reg is edi: gcrootmap.add_edi(shape) else: - assert reg is eax # ok to ignore this one + print "[get_mark_gc_roots] bogus register", reg + assert False return gcrootmap.compress_callshape(shape) def consider_force_token(self, op): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/ri386.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/ri386.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/ri386.py Tue Jun 8 19:48:40 2010 @@ -210,7 +210,7 @@ class REL32(OPERAND): width = 4 def __init__(self, absolute_target): - self.absolute_target = absolute_target + self.absolute_target = get_real_int(absolute_target) def assembler(self): return '%d' % (self.absolute_target,) @@ -286,11 +286,14 @@ rel32 = REL32 rel8 = REL8 +def get_real_int(x): + from pypy.rpython.lltypesystem import rffi, lltype + return rffi.cast(lltype.Signed, x) # force as a real int + def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() - if not we_are_translated(): - assert type(value) is int + value = get_real_int(value) if single_byte(value): return imm8(value) else: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/runner.py Tue Jun 8 19:48:40 2010 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp import history, compile @@ -67,19 +68,20 @@ return self.assembler.fail_boxes_float.getitem(index) def get_latest_value_ref(self, index): - ptrvalue = self.assembler.fail_boxes_ptr.getitem(index) - # clear after reading - self.assembler.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - return ptrvalue + return self.assembler.fail_boxes_ptr.getitem(index) + + def get_latest_value_count(self): + return self.assembler.fail_boxes_count + + def clear_latest_values(self, count): + setitem = self.assembler.fail_boxes_ptr.setitem + null = lltype.nullptr(llmemory.GCREF.TO) + for index in range(count): + setitem(index, null) def get_latest_force_token(self): return self.assembler.fail_ebp + FORCE_INDEX_OFS - def make_boxes_from_latest_values(self, faildescr): - return self.assembler.make_boxes_from_latest_values( - faildescr._x86_failure_recovery_bytecode) - def execute_token(self, executable_token): addr = executable_token._x86_bootstrap_code func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr) @@ -136,9 +138,6 @@ CPU = CPU386 -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(CPU) - # silence warnings history.LoopToken._x86_param_depth = 0 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/support.py Tue Jun 8 19:48:40 2010 @@ -4,6 +4,8 @@ ATP = lltype.GcArray(TP) class ValuesArray(object): + SIZE = size + def __init__(self): self.ar = lltype.malloc(ATP, size, zero=True, immortal=True) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_assembler.py Tue Jun 8 19:48:40 2010 @@ -75,35 +75,6 @@ assert ([loc.assembler() for loc in newlocs] == [loc.assembler() for loc in locs if loc is not None]) - # finally, test make_boxes_from_latest_values(), which should - # reproduce the holes - expected_classes = [BoxInt, BoxPtr, BoxFloat, - BoxInt, BoxPtr, BoxFloat, - type(None), type(None), - BoxInt, BoxPtr, BoxFloat] - ptrvalues = {} - S = lltype.GcStruct('S') - for i, cls in enumerate(expected_classes): - if cls == BoxInt: - assembler.fail_boxes_int.setitem(i, 1000 + i) - elif cls == BoxPtr: - s = lltype.malloc(S) - s_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s) - ptrvalues[i] = s_ref - assembler.fail_boxes_ptr.setitem(i, s_ref) - elif cls == BoxFloat: - assembler.fail_boxes_float.setitem(i, 42.5 + i) - boxes = assembler.make_boxes_from_latest_values(bytecode_addr) - assert len(boxes) == len(locs) == len(expected_classes) - for i, (box, expected_class) in enumerate(zip(boxes, expected_classes)): - assert type(box) is expected_class - if expected_class == BoxInt: - assert box.value == 1000 + i - elif expected_class == BoxPtr: - assert box.value == ptrvalues[i] - elif expected_class == BoxFloat: - assert box.value == 42.5 + i - # ____________________________________________________________ def test_failure_recovery_func_no_floats(): @@ -244,6 +215,13 @@ # bits of the float were correctly saved and restored. assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + # verify that until clear_latest_values() is called, reading the + # same values multiple times work + for i in range(len(content)): + assert assembler.fail_boxes_int.getitem(i) == expected_ints[i] + assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i] + assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + class FakeProfileAgent(object): def __init__(self): self.functions = [] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_basic.py Tue Jun 8 19:48:40 2010 @@ -2,7 +2,7 @@ from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.test import test_basic -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE class Jit386Mixin(test_basic.LLJitMixin): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_gc_integration.py Tue Jun 8 19:48:40 2010 @@ -6,6 +6,7 @@ from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription from pypy.jit.backend.x86.runner import CPU @@ -225,10 +226,12 @@ self.nodedescr = nodedescr vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) vtable_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable)) - NODE2 = lltype.Struct('node2', ('tid', lltype.Signed), + NODE2 = lltype.GcStruct('node2', + ('parent', rclass.OBJECT), + ('tid', lltype.Signed), ('vtable', lltype.Ptr(rclass.OBJECT_VTABLE))) descrsize = cpu.sizeof(NODE2) - cpu.set_class_sizes({vtable_int: descrsize}) + heaptracker.register_known_gctype(cpu, vtable, NODE2) self.descrsize = descrsize self.vtable_int = vtable_int @@ -282,4 +285,4 @@ assert gc_ll_descr.nursery[0] == self.descrsize.tid assert gc_ll_descr.nursery[1] == self.vtable_int nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + 8 + assert gc_ll_descr.addrs[0] == nurs_adr + 12 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc.py Tue Jun 8 19:48:40 2010 @@ -211,10 +211,9 @@ ''' S = lltype.GcStruct('S') ptr = lltype.malloc(S) + self.cpu.clear_latest_values(2) self.interpret(ops, [0, ptr]) assert self.getptr(0, lltype.Ptr(S)) == ptr - assert not self.cpu.assembler.fail_boxes_ptr.getitem(0) - assert not self.cpu.assembler.fail_boxes_ptr.getitem(1) def test_exception_bridge_no_exception(self): ops = ''' @@ -522,18 +521,20 @@ assert self.getint(0) == 0 def test_bug_float_is_true_stack(self): + # NB. float_is_true no longer exists. Unsure if keeping this test + # makes sense any more. ops = ''' [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9] - i0 = float_is_true(f0) - i1 = float_is_true(f1) - i2 = float_is_true(f2) - i3 = float_is_true(f3) - i4 = float_is_true(f4) - i5 = float_is_true(f5) - i6 = float_is_true(f6) - i7 = float_is_true(f7) - i8 = float_is_true(f8) - i9 = float_is_true(f9) + i0 = float_ne(f0, 0.0) + i1 = float_ne(f1, 0.0) + i2 = float_ne(f2, 0.0) + i3 = float_ne(f3, 0.0) + i4 = float_ne(f4, 0.0) + i5 = float_ne(f5, 0.0) + i6 = float_ne(f6, 0.0) + i7 = float_ne(f7, 0.0) + i8 = float_ne(f8, 0.0) + i9 = float_ne(f9, 0.0) finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) ''' loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9]) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_regalloc2.py Tue Jun 8 19:48:40 2010 @@ -35,7 +35,7 @@ ResOperation(rop.INT_MUL, [v1, v1], v2), ResOperation(rop.INT_MUL, [v2, v1], v3), ResOperation(rop.INT_IS_TRUE, [v2], tmp5), - ResOperation(rop.BOOL_NOT, [tmp5], v4), + ResOperation(rop.INT_IS_ZERO, [tmp5], v4), ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()), ] cpu = CPU(None, None) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_runner.py Tue Jun 8 19:48:40 2010 @@ -259,9 +259,11 @@ self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) if guard == rop.GUARD_FALSE: - assert result == execute(self.cpu, op, None, b).value + assert result == execute(self.cpu, None, + op, None, b).value else: - assert result != execute(self.cpu, op, None, b).value + assert result != execute(self.cpu, None, + op, None, b).value def test_stuff_followed_by_guard(self): @@ -304,7 +306,7 @@ self.cpu.set_future_value_int(i, box.value) self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) - expected = execute(self.cpu, op, None, a, b).value + expected = execute(self.cpu, None, op, None, a, b).value if guard == rop.GUARD_FALSE: assert result == expected else: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_send.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_send.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_send.py Tue Jun 8 19:48:40 2010 @@ -2,7 +2,6 @@ import py from pypy.jit.metainterp.test.test_send import SendTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rlib import jit class TestSend(Jit386Mixin, SendTests): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_zrpy_gc.py Tue Jun 8 19:48:40 2010 @@ -94,7 +94,7 @@ def run(cbuilder, args=''): # pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': str(pypylog)}) + data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) return data.strip() def compile_and_run(f, gc, **kwds): @@ -174,7 +174,7 @@ def run(self, name, n=2000): pypylog = udir.join('TestCompileHybrid.log') res = self.cbuilder.cmdexec("%s %d" %(name, n), - env={'PYPYLOG': str(pypylog)}) + env={'PYPYLOG': ':%s' % pypylog}) assert int(res) == 20 def run_orig(self, name, n, x): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_ztranslation.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_ztranslation.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/backend/x86/test/test_ztranslation.py Tue Jun 8 19:48:40 2010 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.jitprof import Profiler from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.backend.test.support import CCompiledMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.translator.translator import TranslationContext class TestTranslationX86(CCompiledMixin): @@ -38,7 +38,7 @@ return abs(x) jitdriver = JitDriver(greens = [], - reds = ['frame', 'total', 'j'], + reds = ['total', 'frame', 'j'], virtualizables = ['frame']) def f(i, j): for param in unroll_parameters: @@ -72,7 +72,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -127,8 +127,14 @@ def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) + class ImDone(Exception): + def __init__(self, resvalue): + self.resvalue = resvalue + @dont_look_inside - def f(x): + def f(x, total): + if x <= 3: + raise ImDone(total * 10) if x > 20: return 2 raise ValueError @@ -149,16 +155,16 @@ return Sub() else: return Base() - def main(i): + def myportal(i): jitdriver.set_param("threshold", 3) jitdriver.set_param("trace_eagerness", 2) total = 0 n = i - while n > 3: + while True: jitdriver.can_enter_jit(n=n, total=total) jitdriver.jit_merge_point(n=n, total=total) try: - total += f(n) + total += f(n, total) except ValueError: total += 1 try: @@ -166,7 +172,11 @@ except ValueError: total -= 1 n -= h(n).meth() # this is to force a GUARD_CLASS - return total * 10 + def main(i): + try: + myportal(i) + except ImDone, e: + return e.resvalue # XXX custom fishing, depends on the exact env var and format logfile = udir.join('test_ztranslation.log') Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/support.py ============================================================================== --- pypy/branch/blackhole-improvement/pypy/jit/codewriter/support.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/support.py Tue Jun 8 19:48:40 2010 @@ -42,7 +42,7 @@ annpolicy.allow_someobjects = False a = t.buildannotator(policy=annpolicy) argtypes = getargtypes(a, values) - a.build_types(func, argtypes) + a.build_types(func, argtypes, main_entry_point=True) rtyper = t.buildrtyper(type_system = type_system) rtyper.specialize() if inline: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/compile.py Tue Jun 8 19:48:40 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import debug_start, debug_stop from pypy.conftest import option +from pypy.tool.sourcetools import func_with_new_name from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import TreeLoop, Box, History, LoopToken @@ -14,8 +15,10 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.jit.metainterp.optimizeutil import InvalidLoop -class GiveUp(Exception): - pass +def giveup(): + from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole + from pypy.jit.metainterp.jitprof import ABORT_BRIDGE + raise SwitchToBlackhole(ABORT_BRIDGE) def show_loop(metainterp_sd, loop=None, error=None): # debugging @@ -153,6 +156,7 @@ assert metainterp_sd.result_type == 'ref' cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): @@ -165,6 +169,7 @@ def handle_fail(self, metainterp_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value) @@ -220,6 +225,11 @@ rd_virtuals = None rd_pendingfields = None + CNT_INT = -0x20000000 + CNT_REF = -0x40000000 + CNT_FLOAT = -0x60000000 + CNT_MASK = 0x1FFFFFFF + def __init__(self, metainterp_sd, original_greenkey): ResumeDescr.__init__(self, original_greenkey) self.metainterp_sd = metainterp_sd @@ -236,23 +246,64 @@ except ValueError: return # xxx probably very rare else: - self._counter = ~i # use ~(index_of_guarded_box_in_fail_args) + if box.type == history.INT: + cnt = self.CNT_INT + elif box.type == history.REF: + cnt = self.CNT_REF + elif box.type == history.FLOAT: + cnt = self.CNT_FLOAT + else: + assert 0, box.type + # we build the following value for _counter, which is always + # a negative value + self._counter = cnt | i def handle_fail(self, metainterp_sd): + if self.must_compile(metainterp_sd): + return self._trace_and_compile_from_bridge(metainterp_sd) + else: + from pypy.jit.metainterp.blackhole import resume_in_blackhole + resume_in_blackhole(metainterp_sd, self) + assert 0, "unreachable" + + def _trace_and_compile_from_bridge(self, metainterp_sd): from pypy.jit.metainterp.pyjitpl import MetaInterp metainterp = MetaInterp(metainterp_sd) return metainterp.handle_guard_failure(self) + _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd, inputargs_and_holes): + def must_compile(self, metainterp_sd): trace_eagerness = metainterp_sd.state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness else: - box = inputargs_and_holes[~self._counter] - if self._counters is None: - self._counters = ResumeGuardCounters() - counter = self._counters.see(box) + index = self._counter & self.CNT_MASK + typetag = self._counter & ~ self.CNT_MASK + counters = self._counters + if typetag == self.CNT_INT: + intvalue = metainterp_sd.cpu.get_latest_value_int(index) + if counters is None: + self._counters = counters = ResumeGuardCountersInt() + else: + assert isinstance(counters, ResumeGuardCountersInt) + counter = counters.see_int(intvalue) + elif typetag == self.CNT_REF: + refvalue = metainterp_sd.cpu.get_latest_value_ref(index) + if counters is None: + self._counters = counters = ResumeGuardCountersRef() + else: + assert isinstance(counters, ResumeGuardCountersRef) + counter = counters.see_ref(refvalue) + elif typetag == self.CNT_FLOAT: + floatvalue = metainterp_sd.cpu.get_latest_value_float(index) + if counters is None: + self._counters = counters = ResumeGuardCountersFloat() + else: + assert isinstance(counters, ResumeGuardCountersFloat) + counter = counters.see_float(floatvalue) + else: + assert 0, typetag return counter >= trace_eagerness def reset_counter_from_failure(self): @@ -283,17 +334,17 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): def handle_fail(self, metainterp_sd): - from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + # Failures of a GUARD_NOT_FORCED are never compiled, but + # always just blackholed. First fish for the data saved when + # the virtualrefs and virtualizable have been forced by + # handle_async_forcing() just a moment ago. + from pypy.jit.metainterp.blackhole import resume_in_blackhole token = metainterp_sd.cpu.get_latest_force_token() all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - metainterp._already_allocated_resume_virtuals = all_virtuals - return metainterp.handle_guard_failure(self) - - def must_compile(self, metainterp_sd, inputargs_and_holes): - return False # never compile GUARD_NOT_FORCED failures + resume_in_blackhole(metainterp_sd, self, all_virtuals) + assert 0, "unreachable" @staticmethod def force_now(cpu, token): @@ -305,91 +356,101 @@ faildescr.handle_async_forcing(token) def handle_async_forcing(self, force_token): - from pypy.jit.metainterp.pyjitpl import MetaInterp from pypy.jit.metainterp.resume import force_from_resumedata - # To handle the forcing itself, we create a temporary MetaInterp - # as a convenience to move the various data to its proper place. metainterp_sd = self.metainterp_sd - metainterp = MetaInterp(metainterp_sd) - metainterp.history = None # blackholing - liveboxes = metainterp_sd.cpu.make_boxes_from_latest_values(self) - # - expect_virtualizable = metainterp_sd.virtualizable_info is not None - forced_data = force_from_resumedata(metainterp, liveboxes, self, - expect_virtualizable) - virtualizable_boxes, virtualref_boxes, all_virtuals = forced_data - # - # Handle virtualref_boxes: mark each JIT_VIRTUAL_REF as forced - vrefinfo = metainterp_sd.virtualref_info - for i in range(0, len(virtualref_boxes), 2): - virtualbox = virtualref_boxes[i] - vrefbox = virtualref_boxes[i+1] - vrefinfo.forced_single_vref(vrefbox.getref_base(), - virtualbox.getref_base()) - # Handle virtualizable_boxes: store them on the real virtualizable now - if expect_virtualizable: - metainterp_sd.virtualizable_info.forced_vable(virtualizable_boxes) + all_virtuals = force_from_resumedata(metainterp_sd, self) + # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED self.save_data(force_token, all_virtuals) def save_data(self, key, value): globaldata = self.metainterp_sd.globaldata - assert key not in globaldata.resume_virtuals - globaldata.resume_virtuals[key] = value + if we_are_translated(): + assert key not in globaldata.resume_virtuals + globaldata.resume_virtuals[key] = value + else: + rv = globaldata.resume_virtuals_not_translated + for key1, value1 in rv: + assert key1 != key + rv.append((key, value)) def fetch_data(self, key): globaldata = self.metainterp_sd.globaldata - assert key in globaldata.resume_virtuals - data = globaldata.resume_virtuals[key] - del globaldata.resume_virtuals[key] + if we_are_translated(): + assert key in globaldata.resume_virtuals + data = globaldata.resume_virtuals[key] + del globaldata.resume_virtuals[key] + else: + rv = globaldata.resume_virtuals_not_translated + for i in range(len(rv)): + if rv[i][0] == key: + data = rv[i][1] + del rv[i] + break + else: + assert 0, "not found: %r" % (key,) return data -class ResumeGuardCounters(object): - # Completely custom algorithm for now: keep 5 pairs (box, counter), +class AbstractResumeGuardCounters(object): + # Completely custom algorithm for now: keep 5 pairs (value, counter), # and when we need more, we discard the middle pair (middle in the # current value of the counter). That way, we tend to keep the - # boxes with a high counter, but also we avoid always throwing away - # the most recently added box. **THIS ALGO MUST GO AWAY AT SOME POINT** + # values with a high counter, but also we avoid always throwing away + # the most recently added value. **THIS ALGO MUST GO AWAY AT SOME POINT** + pass +def _see(self, newvalue): + # find and update an existing counter + unused = -1 + for i in range(5): + cnt = self.counters[i] + if cnt: + if self.values[i] == newvalue: + cnt += 1 + self.counters[i] = cnt + return cnt + else: + unused = i + # not found. Use a previously unused entry, if there is one + if unused >= 0: + self.counters[unused] = 1 + self.values[unused] = newvalue + return 1 + # no unused entry. Overwrite the middle one. Computed with indices + # a, b, c meaning the highest, second highest, and third highest + # entries. + a = 0 + b = c = -1 + for i in range(1, 5): + if self.counters[i] > self.counters[a]: + c = b; b = a; a = i + elif b < 0 or self.counters[i] > self.counters[b]: + c = b; b = i + elif c < 0 or self.counters[i] > self.counters[c]: + c = i + self.counters[c] = 1 + self.values[c] = newvalue + return 1 + +class ResumeGuardCountersInt(AbstractResumeGuardCounters): def __init__(self): self.counters = [0] * 5 - self.boxes = [None] * 5 + self.values = [0] * 5 + see_int = func_with_new_name(_see, 'see_int') - def see(self, newbox): - newbox = newbox.constbox() - # find and update an existing counter - unused = -1 - for i in range(5): - cnt = self.counters[i] - if cnt: - if newbox.same_constant(self.boxes[i]): - cnt += 1 - self.counters[i] = cnt - return cnt - else: - unused = i - # not found. Use a previously unused entry, if there is one - if unused >= 0: - self.counters[unused] = 1 - self.boxes[unused] = newbox - return 1 - # no unused entry. Overwrite the middle one. Computed with indices - # a, b, c meaning the highest, second highest, and third highest - # entries. - a = 0 - b = c = -1 - for i in range(1, 5): - if self.counters[i] > self.counters[a]: - c = b; b = a; a = i - elif b < 0 or self.counters[i] > self.counters[b]: - c = b; b = i - elif c < 0 or self.counters[i] > self.counters[c]: - c = i - self.counters[c] = 1 - self.boxes[c] = newbox - return 1 +class ResumeGuardCountersRef(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [history.ConstPtr.value] * 5 + see_ref = func_with_new_name(_see, 'see_ref') + +class ResumeGuardCountersFloat(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [0.0] * 5 + see_float = func_with_new_name(_see, 'see_float') class ResumeFromInterpDescr(ResumeDescr): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/executor.py Tue Jun 8 19:48:40 2010 @@ -2,248 +2,232 @@ """ import py -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, check_descr -from pypy.jit.metainterp.history import INT, REF, ConstFloat +from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, check_descr +from pypy.jit.metainterp.history import INT, REF, FLOAT, VOID, AbstractDescr from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop - - -# Operations in the _ALWAYS_PURE part of the table of resoperation.py -# must return a ConstInt or ConstPtr. Other operations must return -# a BoxInt or BoxPtr or None. +from pypy.jit.metainterp.blackhole import BlackholeInterpreter, NULL # ____________________________________________________________ -def do_int_add(cpu, box1, box2): - return ConstInt(intmask(box1.getint() + box2.getint())) - -def do_int_sub(cpu, box1, box2): - return ConstInt(intmask(box1.getint() - box2.getint())) - -def do_int_mul(cpu, box1, box2): - return ConstInt(intmask(box1.getint() * box2.getint())) - -def do_int_floordiv(cpu, box1, box2): - z = llop.int_floordiv(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_uint_floordiv(cpu, box1, box2): - z = llop.uint_floordiv(lltype.Unsigned, r_uint(box1.getint()), - r_uint(box2.getint())) - return ConstInt(intmask(z)) - -def do_int_mod(cpu, box1, box2): - z = llop.int_mod(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_int_and(cpu, box1, box2): - return ConstInt(box1.getint() & box2.getint()) - -def do_int_or(cpu, box1, box2): - return ConstInt(box1.getint() | box2.getint()) - -def do_int_xor(cpu, box1, box2): - return ConstInt(box1.getint() ^ box2.getint()) - -def do_int_rshift(cpu, box1, box2): - return ConstInt(box1.getint() >> box2.getint()) - -def do_int_lshift(cpu, box1, box2): - return ConstInt(intmask(box1.getint() << box2.getint())) - -def do_uint_rshift(cpu, box1, box2): - v = r_uint(box1.getint()) >> r_uint(box2.getint()) - return ConstInt(intmask(v)) - -# ---------- - -def do_int_lt(cpu, box1, box2): - return ConstInt(box1.getint() < box2.getint()) - -def do_int_le(cpu, box1, box2): - return ConstInt(box1.getint() <= box2.getint()) - -def do_int_eq(cpu, box1, box2): - return ConstInt(box1.getint() == box2.getint()) - -def do_int_ne(cpu, box1, box2): - return ConstInt(box1.getint() != box2.getint()) - -def do_int_gt(cpu, box1, box2): - return ConstInt(box1.getint() > box2.getint()) - -def do_int_ge(cpu, box1, box2): - return ConstInt(box1.getint() >= box2.getint()) - -def do_uint_lt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) < r_uint(box2.getint())) - -def do_uint_le(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) <= r_uint(box2.getint())) - -def do_uint_gt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) > r_uint(box2.getint())) - -def do_uint_ge(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) >= r_uint(box2.getint())) - -# ---------- - -def do_int_is_true(cpu, box1): - return ConstInt(bool(box1.getint())) - -def do_int_neg(cpu, box1): - return ConstInt(intmask(-box1.getint())) - -def do_int_invert(cpu, box1): - return ConstInt(~box1.getint()) - -def do_bool_not(cpu, box1): - return ConstInt(not box1.getint()) +def _prepare_call(argboxes, descr): + # count the number of arguments of the different types + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + type = argboxes[i].type + if type == INT: count_i += 1 + elif type == REF: count_r += 1 + elif type == FLOAT: count_f += 1 + # allocate lists for each type that has at least one argument + if count_i: args_i = [0] * count_i + else: args_i = None + if count_r: args_r = [NULL] * count_r + else: args_r = None + if count_f: args_f = [0.0] * count_f + else: args_f = None + # fill in the lists + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + box = argboxes[i] + if box.type == INT: + args_i[count_i] = box.getint() + count_i += 1 + elif box.type == REF: + args_r[count_r] = box.getref_base() + count_r += 1 + elif box.type == FLOAT: + args_f[count_f] = box.getfloat() + count_f += 1 + # get the function address as an integer + func = argboxes[0].getint() + # do the call using the correct function from the cpu + rettype = descr.get_return_type() + return func, args_i, args_r, args_f, rettype + +def do_call(cpu, metainterp, argboxes, descr): + assert metainterp is not None + func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) + if rettype == INT: + try: + result = cpu.bh_call_i(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0 + return BoxInt(result) + if rettype == REF: + try: + result = cpu.bh_call_r(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = NULL + return BoxPtr(result) + if rettype == FLOAT: + try: + result = cpu.bh_call_f(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0.0 + return BoxFloat(result) + if rettype == VOID: + try: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + return None + raise AssertionError("bad rettype") + +do_call_loopinvariant = do_call +do_call_may_force = do_call + +def do_call_pure(cpu, _, argboxes, descr): + # this version does not deal with exceptions at all + # xxx in case of MemoryError, it crashes the JIT + func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) + if rettype == INT: + return BoxInt(cpu.bh_call_i(func, descr, args_i, args_r, args_f)) + if rettype == REF: + return BoxPtr(cpu.bh_call_r(func, descr, args_i, args_r, args_f)) + if rettype == FLOAT: + return BoxFloat(cpu.bh_call_f(func, descr, args_i, args_r, args_f)) + if rettype == VOID: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + return None + raise AssertionError("bad rettype") + +def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + return BoxPtr(cpu.bh_getarrayitem_gc_r(arraydescr, array, index)) + elif arraydescr.is_array_of_floats(): + return BoxFloat(cpu.bh_getarrayitem_gc_f(arraydescr, array, index)) + else: + return BoxInt(cpu.bh_getarrayitem_gc_i(arraydescr, array, index)) -def do_same_as(cpu, box1): - return box1 +def do_setarrayitem_gc(cpu, _, arraybox, indexbox, itembox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + cpu.bh_setarrayitem_gc_r(arraydescr, array, index, + itembox.getref_base()) + elif arraydescr.is_array_of_floats(): + cpu.bh_setarrayitem_gc_f(arraydescr, array, index, itembox.getfloat()) + else: + cpu.bh_setarrayitem_gc_i(arraydescr, array, index, itembox.getint()) -def do_oois(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() == box2.getint() - elif tp == REF: - x = box1.getref_base() == box2.getref_base() +def do_getfield_gc(cpu, _, structbox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr)) -def do_ooisnot(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() != box2.getint() - elif tp == REF: - x = box1.getref_base() != box2.getref_base() +def do_getfield_raw(cpu, _, structbox, fielddescr): + check_descr(fielddescr) + struct = structbox.getint() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr)) -def do_subclassof(cpu, box1, box2): - return ConstInt(cpu.ts.subclassOf(cpu, box1, box2)) +def do_setfield_gc(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_gc_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_gc_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_gc_i(struct, fielddescr, itembox.getint()) -# ---------- +def do_setfield_raw(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getint() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_raw_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_raw_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_raw_i(struct, fielddescr, itembox.getint()) -def do_int_add_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def exec_new_with_vtable(cpu, clsbox): + from pypy.jit.codewriter import heaptracker + vtable = clsbox.getint() + descr = heaptracker.vtable2descr(cpu, vtable) + return cpu.bh_new_with_vtable(descr, vtable) + +def do_new_with_vtable(cpu, _, clsbox): + return BoxPtr(exec_new_with_vtable(cpu, clsbox)) + +def do_arraycopy(cpu, _, calldescr, funcbox, x1box, x2box, + x3box, x4box, x5box, arraydescr): + cpu.bh_call_v(funcbox.getint(), calldescr, + [x3box.getint(), x4box.getint(), x5box.getint()], + [x1box.getref_base(), x2box.getref_base()], None) + +def do_int_add_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x + y) + z = ovfcheck(a + b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_sub_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_sub_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x - y) + z = ovfcheck(a - b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_mul_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_mul_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x * y) + z = ovfcheck(a * b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -# ---------- - -def do_float_neg(cpu, box1): - return ConstFloat(-box1.getfloat()) - -def do_float_abs(cpu, box1): - return ConstFloat(abs(box1.getfloat())) - -def do_float_is_true(cpu, box1): - return ConstInt(bool(box1.getfloat())) - -def do_float_add(cpu, box1, box2): - return ConstFloat(box1.getfloat() + box2.getfloat()) - -def do_float_sub(cpu, box1, box2): - return ConstFloat(box1.getfloat() - box2.getfloat()) - -def do_float_mul(cpu, box1, box2): - return ConstFloat(box1.getfloat() * box2.getfloat()) - -def do_float_truediv(cpu, box1, box2): - return ConstFloat(box1.getfloat() / box2.getfloat()) - -def do_float_lt(cpu, box1, box2): - return ConstInt(box1.getfloat() < box2.getfloat()) - -def do_float_le(cpu, box1, box2): - return ConstInt(box1.getfloat() <= box2.getfloat()) - -def do_float_eq(cpu, box1, box2): - return ConstInt(box1.getfloat() == box2.getfloat()) - -def do_float_ne(cpu, box1, box2): - return ConstInt(box1.getfloat() != box2.getfloat()) - -def do_float_gt(cpu, box1, box2): - return ConstInt(box1.getfloat() > box2.getfloat()) - -def do_float_ge(cpu, box1, box2): - return ConstInt(box1.getfloat() >= box2.getfloat()) - -def do_cast_float_to_int(cpu, box1): - # note: we need to call int() twice to care for the fact that - # int(-2147483648.0) returns a long :-( - return ConstInt(int(int(box1.getfloat()))) - -def do_cast_int_to_float(cpu, box1): - return ConstFloat(float(box1.getint())) +def do_same_as(cpu, _, box): + return box.clonebox() # ____________________________________________________________ -def do_force_token(cpu): - raise NotImplementedError +##def do_force_token(cpu): +## raise NotImplementedError -def do_virtual_ref(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref(cpu, box1, box2): +## raise NotImplementedError -def do_virtual_ref_finish(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref_finish(cpu, box1, box2): +## raise NotImplementedError -def do_debug_merge_point(cpu, box1): - from pypy.jit.metainterp.warmspot import get_stats - loc = box1._get_str() - get_stats().add_merge_point_location(loc) +##def do_debug_merge_point(cpu, box1): +## from pypy.jit.metainterp.warmspot import get_stats +## loc = box1._get_str() +## get_stats().add_merge_point_location(loc) # ____________________________________________________________ -def make_execute_list(cpuclass): - from pypy.jit.backend.model import AbstractCPU +def _make_execute_list(): if 0: # enable this to trace calls to do_xxx def wrap(fn): def myfn(*args): @@ -266,37 +250,109 @@ # find which list to store the operation in, based on num_args num_args = resoperation.oparity[value] withdescr = resoperation.opwithdescr[value] - if withdescr and num_args >= 0: - num_args += 1 - if num_args not in execute_by_num_args: - execute_by_num_args[num_args] = [None] * (rop._LAST+1) - execute = execute_by_num_args[num_args] + dictkey = num_args, withdescr + if dictkey not in execute_by_num_args: + execute_by_num_args[dictkey] = [None] * (rop._LAST+1) + execute = execute_by_num_args[dictkey] # if execute[value] is not None: - raise Exception("duplicate entry for op number %d" % value) + raise AssertionError("duplicate entry for op number %d"% value) + # + # Fish for a way for the pyjitpl interpreter to delegate + # really running the operation to the blackhole interpreter + # or directly to the cpu. First try the do_xxx() functions + # explicitly encoded above: + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # Maybe the same without the _PURE suffix? if key.endswith('_PURE'): key = key[:-5] - name = 'do_' + key.lower() - if hasattr(cpuclass, name): - execute[value] = wrap(getattr(cpuclass, name)) - elif name in globals(): - execute[value] = wrap(globals()[name]) - else: - assert hasattr(AbstractCPU, name), name - cpuclass._execute_by_num_args = execute_by_num_args + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # If missing, fallback to the bhimpl_xxx() method of the + # blackhole interpreter. This only works if there is a + # method of the exact same name and it accepts simple + # parameters. + name = 'bhimpl_' + key.lower() + if hasattr(BlackholeInterpreter, name): + func = make_execute_function_with_boxes( + key.lower(), + getattr(BlackholeInterpreter, name).im_func) + if func is not None: + execute[value] = func + continue + if value in (rop.FORCE_TOKEN, + rop.CALL_ASSEMBLER, + rop.COND_CALL_GC_WB, + rop.DEBUG_MERGE_POINT, + rop.SETARRAYITEM_RAW, + ): # list of opcodes never executed by pyjitpl + continue + raise AssertionError("missing %r" % (key,)) + return execute_by_num_args +def make_execute_function_with_boxes(name, func): + # Make a wrapper for 'func'. The func is a simple bhimpl_xxx function + # from the BlackholeInterpreter class. The wrapper is a new function + # that receives and returns boxed values. + for argtype in func.argtypes: + if argtype not in ('i', 'r', 'f', 'd', 'cpu'): + return None + if list(func.argtypes).count('d') > 1: + return None + if func.resulttype not in ('i', 'r', 'f', None): + return None + argtypes = unrolling_iterable(func.argtypes) + resulttype = func.resulttype + # + def do(cpu, _, *argboxes): + newargs = () + for argtype in argtypes: + if argtype == 'cpu': + value = cpu + elif argtype == 'd': + value = argboxes[-1] + assert isinstance(value, AbstractDescr) + argboxes = argboxes[:-1] + else: + argbox = argboxes[0] + argboxes = argboxes[1:] + if argtype == 'i': value = argbox.getint() + elif argtype == 'r': value = argbox.getref_base() + elif argtype == 'f': value = argbox.getfloat() + newargs = newargs + (value,) + assert not argboxes + # + result = func(*newargs) + # + if resulttype == 'i': return BoxInt(result) + if resulttype == 'r': return BoxPtr(result) + if resulttype == 'f': return BoxFloat(result) + return None + # + do.func_name = 'do_' + name + return do -def get_execute_funclist(cpu, num_args): +def get_execute_funclist(num_args, withdescr): # workaround, similar to the next one - return cpu._execute_by_num_args[num_args] + return EXECUTE_BY_NUM_ARGS[num_args, withdescr] get_execute_funclist._annspecialcase_ = 'specialize:memo' -def get_execute_function(cpu, opnum, num_args): +def get_execute_function(opnum, num_args, withdescr): # workaround for an annotation limitation: putting this code in # a specialize:memo function makes sure the following line is # constant-folded away. Only works if opnum and num_args are # constants, of course. - return cpu._execute_by_num_args[num_args][opnum] + func = EXECUTE_BY_NUM_ARGS[num_args, withdescr][opnum] + assert func is not None, "EXECUTE_BY_NUM_ARGS[%s, %s][%s]" % ( + num_args, withdescr, resoperation.opname[opnum]) + return func get_execute_function._annspecialcase_ = 'specialize:memo' def has_descr(opnum): @@ -305,56 +361,61 @@ has_descr._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, descr, *argboxes): +def execute(cpu, metainterp, opnum, descr, *argboxes): # only for opnums with a fixed arity - if has_descr(opnum): + num_args = len(argboxes) + withdescr = has_descr(opnum) + if withdescr: check_descr(descr) argboxes = argboxes + (descr,) else: assert descr is None - func = get_execute_function(cpu, opnum, len(argboxes)) - assert func is not None - return func(cpu, *argboxes) -execute._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, num_args, withdescr) + return func(cpu, metainterp, *argboxes) # note that the 'argboxes' tuple + # optionally ends with the descr +execute._annspecialcase_ = 'specialize:arg(2)' -def execute_varargs(cpu, opnum, argboxes, descr): +def execute_varargs(cpu, metainterp, opnum, argboxes, descr): # only for opnums with a variable arity (calls, typically) check_descr(descr) - func = get_execute_function(cpu, opnum, -1) - assert func is not None - return func(cpu, argboxes, descr) -execute_varargs._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, -1, True) + return func(cpu, metainterp, argboxes, descr) +execute_varargs._annspecialcase_ = 'specialize:arg(2)' -def execute_nonspec(cpu, opnum, argboxes, descr=None): +def execute_nonspec(cpu, metainterp, opnum, argboxes, descr=None): arity = resoperation.oparity[opnum] assert arity == -1 or len(argboxes) == arity if resoperation.opwithdescr[opnum]: check_descr(descr) if arity == -1: - func = get_execute_funclist(cpu, -1)[opnum] - return func(cpu, argboxes, descr) + func = get_execute_funclist(-1, True)[opnum] + return func(cpu, metainterp, argboxes, descr) if arity == 0: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, descr) + func = get_execute_funclist(0, True)[opnum] + return func(cpu, metainterp, descr) if arity == 1: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], descr) + func = get_execute_funclist(1, True)[opnum] + return func(cpu, metainterp, argboxes[0], descr) if arity == 2: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], descr) + func = get_execute_funclist(2, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], descr) if arity == 3: - func = get_execute_funclist(cpu, 4)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2], descr) + func = get_execute_funclist(3, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2], + descr) else: assert descr is None if arity == 1: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, argboxes[0]) + func = get_execute_funclist(1, False)[opnum] + return func(cpu, metainterp, argboxes[0]) if arity == 2: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], argboxes[1]) + func = get_execute_funclist(2, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1]) if arity == 3: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2]) + func = get_execute_funclist(3, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2]) raise NotImplementedError + + +EXECUTE_BY_NUM_ARGS = _make_execute_list() Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/history.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/history.py Tue Jun 8 19:48:40 2010 @@ -9,6 +9,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -16,6 +17,7 @@ REF = 'r' FLOAT = 'f' HOLE = '_' +VOID = 'v' FAILARGS_LIMIT = 1000 @@ -40,6 +42,7 @@ return "ref" else: raise NotImplementedError("type %s not supported" % TYPE) +getkind._annspecialcase_ = 'specialize:memo' def repr_pointer(box): from pypy.rpython.lltypesystem import rstr @@ -98,7 +101,7 @@ def nonconstbox(self): raise NotImplementedError - def getaddr(self, cpu): + def getaddr(self): raise NotImplementedError def sort_key(self): @@ -125,6 +128,18 @@ def _clone_if_mutable(self): return self + def get_arg_types(self): + """ Implement in call descr. + Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). + """ + raise NotImplementedError + + def get_return_type(self): + """ Implement in call descr. + Must return INT, REF, FLOAT, or 'v' for void. + """ + raise NotImplementedError + def get_extra_info(self): """ Implement in call descr """ @@ -150,6 +165,12 @@ """ raise NotImplementedError + def as_vtable_size_descr(self): + """ Implement for size descr representing objects with vtables. + Returns self. (it's an annotation hack) + """ + raise NotImplementedError + class AbstractFailDescr(AbstractDescr): index = -1 @@ -176,18 +197,13 @@ __slots__ = () @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): - if not we_are_translated(): - # cannot store integers representing casted addresses - # inside ConstInt() instances that are going through - # translation; must use the special ConstAddr instead. - return ConstAddr(x, cpu) - intval = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) @@ -216,15 +232,13 @@ # to get the other behavior (i.e. using this __eq__). if self.__class__ is not other.__class__: return False - if isinstance(self.value, Symbolic): - v1 = "symbolic", id(self.value) - else: - v1 = self.value - if isinstance(other.value, Symbolic): - v2 = "symbolic", id(other.value) - else: - v2 = other.value - return v1 == v2 + try: + return self.value == other.value + except TypeError: + if (isinstance(self.value, Symbolic) and + isinstance(other.value, Symbolic)): + return self.value is other.value + raise def __ne__(self, other): return not (self == other) @@ -232,6 +246,7 @@ class ConstInt(Const): type = INT + value = 0 _attrs_ = ('value',) def __init__(self, value): @@ -250,11 +265,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -275,50 +290,6 @@ CONST_FALSE = ConstInt(0) CONST_TRUE = ConstInt(1) -class ConstAddr(Const): # only for constants built before translation - type = INT - _attrs_ = ('value', 'cpu') - - def __init__(self, adrvalue, cpu): - "NOT_RPYTHON" - assert not we_are_translated() - if isinstance(lltype.typeOf(adrvalue), lltype.Ptr): - adrvalue = llmemory.cast_ptr_to_adr(adrvalue) # convenience - else: - assert lltype.typeOf(adrvalue) == llmemory.Address - self.value = adrvalue - self.cpu = cpu - - def clonebox(self): - return BoxInt(self.cpu.cast_adr_to_int(self.value)) - - nonconstbox = clonebox - - def getint(self): - return self.cpu.cast_adr_to_int(self.value) - - def getaddr(self, cpu): - return self.value - - def _get_hash_(self): - return llmemory.cast_adr_to_int(self.value) - - def set_future_value(self, cpu, j): - cpu.set_future_value_int(j, self.getint()) - - def same_constant(self, other): - assert isinstance(other, Const) - return self.value == other.getaddr(self.cpu) - - def nonnull(self): - return bool(self.value) - - def _getrepr_(self): - return self.value - - def repr_rpython(self): - return repr_rpython(self, 'ca') - class ConstFloat(Const): type = FLOAT value = 0.0 @@ -355,6 +326,8 @@ def repr_rpython(self): return repr_rpython(self, 'cf') +CONST_FZERO = ConstFloat(0.0) + class ConstPtr(Const): type = REF value = lltype.nullptr(llmemory.GCREF.TO) @@ -382,7 +355,7 @@ else: return 0 - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def set_future_value(self, cpu, j): @@ -403,7 +376,13 @@ def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr - return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) + try: + return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), + self.value)) + except lltype.UninitializedMemoryAccess: + return '' + +CONST_NULL = ConstPtr(ConstPtr.value) class ConstObj(Const): type = REF @@ -435,7 +414,7 @@ def set_future_value(self, cpu, j): cpu.set_future_value_ref(j, self.value) -## def getaddr(self, cpu): +## def getaddr(self): ## # so far this is used only when calling ## # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a ## # real addr, but just a key for the dictionary @@ -464,7 +443,7 @@ is_box = True # hint that we want to make links in graphviz from this @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": @@ -527,11 +506,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -598,7 +577,7 @@ return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def _get_hash_(self): @@ -694,6 +673,13 @@ except lltype.DelayedPointer: return -2 # xxx risk of changing hash... +def make_hashable_int(i): + if not we_are_translated() and isinstance(i, llmemory.AddressAsInt): + # Warning: such a hash changes at the time of translation + adr = heaptracker.int2adr(i) + return llmemory.cast_adr_to_int(adr, "emulated") + return i + # ____________________________________________________________ # The TreeLoop class contains a loop or a generalized loop, i.e. a tree @@ -845,16 +831,6 @@ op = ResOperation(opnum, argboxes, resbox, descr) self.operations[position] = op - def slice_history_at(self, position): - """ a strange function that does this: - history : operation_at_position : rest - it'll kill operation_at_position, store everything before that - in history.operations and return rest - """ - rest = self.operations[position + 1:] - del self.operations[position:] - return rest - # ____________________________________________________________ Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitprof.py Tue Jun 8 19:48:40 2010 @@ -5,6 +5,7 @@ import os import time from pypy.rlib.debug import debug_print +from pypy.jit.metainterp.jitexc import JitException counters=""" TRACING @@ -13,7 +14,6 @@ BLACKHOLE OPS RECORDED_OPS -BLACKHOLED_OPS GUARDS OPT_OPS OPT_GUARDS @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 5 # one for TOTAL, 5 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 4 # one for TOTAL, 4 for calls, update if needed class BaseProfiler(object): pass @@ -97,7 +97,7 @@ self.t1 = self.starttime self.times = [0, 0] self.counters = [0] * ncounters - self.calls = [[0, 0], [0, 0], [0, 0]] + self.calls = [[0, 0], [0, 0]] self.current = [] def finish(self): @@ -150,10 +150,10 @@ def count_ops(self, opnum, kind=OPS): from pypy.jit.metainterp.resoperation import rop self.counters[kind] += 1 - if opnum == rop.CALL or opnum == rop.OOSEND: + if opnum == rop.CALL: # or opnum == rop.OOSEND: self.calls[kind-OPS][0] += 1 - elif opnum == rop.CALL_PURE or opnum == rop.OOSEND_PURE: - self.calls[kind-OPS][1] += 1 + elif opnum == rop.CALL_PURE: # or opnum == rop.OOSEND_PURE: + self.calls[kind-OPS][1] += 1 def print_stats(self): cnt = self.counters @@ -172,8 +172,6 @@ self._print_intline(" calls", calls[1][0]) self._print_intline(" pure calls", calls[1][1]) self._print_intline("guards", cnt[GUARDS]) - self._print_intline("blackholed ops", calls[2][0]) - self._print_intline(" pure calls", calls[2][1]) self._print_intline("opt ops", cnt[OPT_OPS]) self._print_intline("opt guards", cnt[OPT_GUARDS]) self._print_intline("forcings", cnt[OPT_FORCINGS]) @@ -195,5 +193,5 @@ -class BrokenProfilerData(Exception): +class BrokenProfilerData(JitException): pass Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/logger.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/logger.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/logger.py Tue Jun 8 19:48:40 2010 @@ -1,9 +1,11 @@ import os from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, \ - BoxInt, ConstAddr, ConstFloat, BoxFloat, AbstractFailDescr + BoxInt, ConstFloat, BoxFloat, AbstractFailDescr class Logger(object): @@ -46,10 +48,16 @@ mv = len(memo) memo[arg] = mv if isinstance(arg, ConstInt): + if int_could_be_an_address(arg.value): + addr = arg.getaddr() + name = self.metainterp_sd.get_name_from_address(addr) + if name: + return 'ConstClass(' + name + ')' return str(arg.value) elif isinstance(arg, BoxInt): return 'i' + str(mv) elif isinstance(arg, self.ts.ConstRef): + # XXX for ootype, this should also go through get_name_from_address return 'ConstPtr(ptr' + str(mv) + ')' elif isinstance(arg, self.ts.BoxRef): return 'p' + str(mv) @@ -57,12 +65,6 @@ return str(arg.value) elif isinstance(arg, BoxFloat): return 'f' + str(mv) - elif isinstance(arg, self.ts.ConstAddr): - addr = arg.getaddr(self.metainterp_sd.cpu) - name = self.metainterp_sd.get_name_from_address(addr) - if not name: - name = 'cls' + str(mv) - return 'ConstClass(' + name + ')' elif arg is None: return 'None' else: @@ -102,3 +104,11 @@ fail_args = '' debug_print(res + op.getopname() + '(' + args + ')' + fail_args) + + +def int_could_be_an_address(x): + if we_are_translated(): + x = rffi.cast(lltype.Signed, x) # force it + return not (-32768 <= x <= 32767) + else: + return isinstance(x, llmemory.AddressAsInt) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizefindnode.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizefindnode.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizefindnode.py Tue Jun 8 19:48:40 2010 @@ -160,7 +160,8 @@ else: # all constant arguments: we can constant-fold argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.set_constant_node(op.result, resbox.constbox()) # default case: mark the arguments as escaping for box in op.args: @@ -169,8 +170,8 @@ def find_nodes_no_escape(self, op): pass # for operations that don't escape their arguments - find_nodes_OOIS = find_nodes_no_escape - find_nodes_OOISNOT = find_nodes_no_escape + find_nodes_PTR_EQ = find_nodes_no_escape + find_nodes_PTR_NE = find_nodes_no_escape find_nodes_INSTANCEOF = find_nodes_no_escape find_nodes_GUARD_NONNULL = find_nodes_no_escape find_nodes_GUARD_ISNULL = find_nodes_no_escape Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeopt.py Tue Jun 8 19:48:40 2010 @@ -16,7 +16,7 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype -from pypy.jit.metainterp.history import AbstractDescr +from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int def optimize_loop_1(metainterp_sd, loop): """Optimize loop.operations to make it match the input of loop.specnodes @@ -89,7 +89,7 @@ if level == LEVEL_KNOWNCLASS: return self.known_class elif level == LEVEL_CONSTANT: - return cpu.ts.cls_of_box(cpu, self.box) + return cpu.ts.cls_of_box(self.box) else: return None @@ -564,7 +564,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) newboxes = modifier.finish(self.values, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here - raise compile.GiveUp + compile.giveup() descr.store_final_boxes(op, newboxes) # if op.opnum == rop.GUARD_VALUE: @@ -594,7 +594,8 @@ else: # all constant arguments: constant-fold away argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.make_constant(op.result, resbox.constbox()) return @@ -747,6 +748,9 @@ def optimize_INT_IS_TRUE(self, op): self._optimize_nullness(op, op.args[0], True) + def optimize_INT_IS_ZERO(self, op): + self._optimize_nullness(op, op.args[0], False) + def _optimize_oois_ooisnot(self, op, expect_isnot): value0 = self.getvalue(op.args[0]) value1 = self.getvalue(op.args[1]) @@ -775,10 +779,10 @@ return self.optimize_default(op) - def optimize_OOISNOT(self, op): + def optimize_PTR_NE(self, op): self._optimize_oois_ooisnot(op, True) - def optimize_OOIS(self, op): + def optimize_PTR_EQ(self, op): self._optimize_oois_ooisnot(op, False) def optimize_VIRTUAL_REF(self, op): @@ -944,7 +948,8 @@ if not funcvalue.is_constant(): self.optimize_default(op) return - resvalue = self.loop_invariant_results.get(op.args[0].getint(), None) + key = make_hashable_int(op.args[0].getint()) + resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: self.make_equal_to(op.result, resvalue) return @@ -953,7 +958,7 @@ op.opnum = rop.CALL self.optimize_default(op) resvalue = self.getvalue(op.result) - self.loop_invariant_results[op.args[0].getint()] = resvalue + self.loop_invariant_results[key] = resvalue def optimize_INT_AND(self, op): v1 = self.getvalue(op.args[0]) @@ -1101,7 +1106,7 @@ del self.cached_arrayitems[arraydescr] except KeyError: pass - if effectinfo.forces_virtual_or_virtualizable: + if effectinfo.check_forces_virtual_or_virtualizable(): vrefinfo = self.optimizer.metainterp_sd.virtualref_info self.force_lazy_setfield(vrefinfo.descr_forced) # ^^^ we only need to force this field; the other fields Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeutil.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeutil.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/optimizeutil.py Tue Jun 8 19:48:40 2010 @@ -2,8 +2,9 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp import resoperation, history +from pypy.jit.metainterp.jitexc import JitException -class InvalidLoop(Exception): +class InvalidLoop(JitException): """Raised when the optimize*.py detect that the loop that we are trying to build cannot possibly make sense as a long-running loop (e.g. it cannot run 2 complete iterations).""" Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py Tue Jun 8 19:48:40 2010 @@ -1,205 +1,170 @@ import py, os -from pypy.rpython.lltypesystem import llmemory -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.debug import make_sure_not_resized +from pypy.rlib import nonconst from pypy.jit.metainterp import history, compile, resume -from pypy.jit.metainterp.history import Const, ConstInt, Box +from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat +from pypy.jit.metainterp.history import Box from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp import codewriter, executor +from pypy.jit.metainterp import executor from pypy.jit.metainterp.logger import Logger -from pypy.jit.metainterp.jitprof import BLACKHOLED_OPS, EmptyProfiler +from pypy.jit.metainterp.jitprof import EmptyProfiler from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE +from pypy.jit.metainterp.jitexc import JitException, get_llexception from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED -from pypy.jit.metainterp.compile import GiveUp +from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ -def check_args(*args): - for arg in args: - assert isinstance(arg, (Box, Const)) - -class arguments(object): - def __init__(self, *argtypes): - self.argtypes = argtypes - - def __eq__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes == other.argtypes - - def __ne__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes != other.argtypes - - def __call__(self, func): - argtypes = unrolling_iterable(self.argtypes) - def wrapped(self, orgpc): - args = (self, ) - for argspec in argtypes: - if argspec == "box": - box = self.load_arg() - args += (box, ) - elif argspec == "constbox": - args += (self.load_const_arg(), ) - elif argspec == "int": - args += (self.load_int(), ) - elif argspec == "jumptarget": - args += (self.load_3byte(), ) - elif argspec == "jumptargets": - num = self.load_int() - args += ([self.load_3byte() for i in range(num)], ) - elif argspec == "varargs": - args += (self.load_varargs(), ) - elif argspec == "constargs": - args += (self.load_constargs(), ) - elif argspec == "descr": - descr = self.load_const_arg() - assert isinstance(descr, history.AbstractDescr) - args += (descr, ) - elif argspec == "bytecode": - bytecode = self.load_const_arg() - assert isinstance(bytecode, codewriter.JitCode) - args += (bytecode, ) - elif argspec == "orgpc": - args += (orgpc, ) - elif argspec == "methdescr": - methdescr = self.load_const_arg() - assert isinstance(methdescr, - history.AbstractMethDescr) - args += (methdescr, ) - else: - assert 0, "unknown argtype declaration: %r" % (argspec,) - val = func(*args) - if val is None: - val = False - return val - name = func.func_name - wrapped.func_name = "wrap_" + name - wrapped.argspec = self - return wrapped +def arguments(*args): + def decorate(func): + func.argtypes = args + return func + return decorate # ____________________________________________________________ class MIFrame(object): - exception_box = None - exc_value_box = None - # for resume.py operation - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - def __init__(self, metainterp, jitcode, greenkey=None): - assert isinstance(jitcode, codewriter.JitCode) + def __init__(self, metainterp): self.metainterp = metainterp + self.registers_i = [None] * 256 + self.registers_r = [None] * 256 + self.registers_f = [None] * 256 + + def setup(self, jitcode, greenkey=None): + assert isinstance(jitcode, JitCode) self.jitcode = jitcode self.bytecode = jitcode.code - self.constants = jitcode.constants - self.exception_target = -1 - self.name = jitcode.name # purely for having name attribute # this is not None for frames that are recursive portal calls self.greenkey = greenkey + # copy the constants in place + self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt) + self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr) + self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat) + self._result_argcode = 'v' + # for resume.py operation + self.parent_resumedata_snapshot = None + self.parent_resumedata_frame_info_list = None + + def copy_constants(self, registers, constants, ConstClass): + """Copy jitcode.constants[0] to registers[255], + jitcode.constants[1] to registers[254], + jitcode.constants[2] to registers[253], etc.""" + if nonconst.NonConstant(0): # force the right type + constants[0] = ConstClass.value # (useful for small tests) + i = len(constants) - 1 + while i >= 0: + j = 255 - i + assert j >= 0 + registers[j] = ConstClass(constants[i]) + i -= 1 + copy_constants._annspecialcase_ = 'specialize:arg(3)' + + def cleanup_registers(self): + # To avoid keeping references alive, this cleans up the registers_r. + # It does not clear the references set by copy_constants(), but + # these are all prebuilt constants anyway. + for i in range(self.jitcode.num_regs_r()): + self.registers_r[i] = None # ------------------------------ # Decoding of the JitCode - def load_int(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - if result > 0x7F: - result = self._load_larger_int(result) - return result - - def _load_larger_int(self, result): # slow path - result = result & 0x7F - shift = 7 - pc = self.pc - while 1: - byte = ord(self.bytecode[pc]) - pc += 1 - result += (byte & 0x7F) << shift - shift += 7 - if not byte & 0x80: - break - self.pc = pc - return intmask(result) - _load_larger_int._dont_inline_ = True - - def load_3byte(self): - pc = self.pc - result = (((ord(self.bytecode[pc + 0])) << 16) | - ((ord(self.bytecode[pc + 1])) << 8) | - ((ord(self.bytecode[pc + 2])) << 0)) - self.pc = pc + 3 - return result - - def load_bool(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - return bool(result) - - def getenv(self, i): - assert i >= 0 - j = i >> 1 - if i & 1: - return self.constants[j] - else: - assert j < len(self.env) - return self.env[j] - - def load_arg(self): - return self.getenv(self.load_int()) - - def load_const_arg(self): - return self.constants[self.load_int()] - - def load_varargs(self): - count = self.load_int() - return [self.load_arg() for i in range(count)] - - def load_constargs(self): - count = self.load_int() - return [self.load_const_arg() for i in range(count)] - - def ignore_varargs(self): - count = self.load_int() + def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): + assert argcode in 'IRF' + code = self.bytecode + length = ord(code[position]) + position += 1 + for i in range(length): + index = ord(code[position+i]) + if argcode == 'I': reg = self.registers_i[index] + elif argcode == 'R': reg = self.registers_r[index] + elif argcode == 'F': reg = self.registers_f[index] + else: raise AssertionError(argcode) + outvalue[startindex+i] = reg + prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' + + def get_current_position_info(self): + return self.jitcode.get_live_vars_info(self.pc) + + def get_list_of_active_boxes(self, in_a_call): + if in_a_call: + # If we are not the topmost frame, self._result_argcode contains + # the type of the result of the call instruction in the bytecode. + # We use it to clear the box that will hold the result: this box + # is not defined yet. + argcode = self._result_argcode + index = ord(self.bytecode[self.pc - 1]) + if argcode == 'i': self.registers_i[index] = history.CONST_FALSE + elif argcode == 'r': self.registers_r[index] = history.CONST_NULL + elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO + self._result_argcode = '?' # done + # + info = self.get_current_position_info() + start_i = 0 + start_r = start_i + info.get_register_count_i() + start_f = start_r + info.get_register_count_r() + total = start_f + info.get_register_count_f() + # allocate a list of the correct size + env = [None] * total + make_sure_not_resized(env) + # fill it now + for i in range(info.get_register_count_i()): + index = info.get_register_index_i(i) + env[start_i + i] = self.registers_i[index] + for i in range(info.get_register_count_r()): + index = info.get_register_index_r(i) + env[start_r + i] = self.registers_r[index] + for i in range(info.get_register_count_f()): + index = info.get_register_index_f(i) + env[start_f + i] = self.registers_f[index] + return env + + def replace_active_box_in_frame(self, oldbox, newbox): + if isinstance(oldbox, history.BoxInt): + count = self.jitcode.num_regs_i() + registers = self.registers_i + elif isinstance(oldbox, history.BoxPtr): + count = self.jitcode.num_regs_r() + registers = self.registers_r + elif isinstance(oldbox, history.BoxFloat): + count = self.jitcode.num_regs_f() + registers = self.registers_f + else: + assert 0, oldbox for i in range(count): - self.load_int() - - def getvarenv(self, i): - return self.env[i] + if registers[i] is oldbox: + registers[i] = newbox + if not we_are_translated(): + assert oldbox not in registers[count:] - def make_result_box(self, box): - assert isinstance(box, Box) or isinstance(box, Const) - self.env.append(box) + def make_result_of_lastop(self, resultbox): + if resultbox is None: + return + target_index = ord(self.bytecode[self.pc-1]) + if resultbox.type == history.INT: + self.registers_i[target_index] = resultbox + elif resultbox.type == history.REF: + #debug_print(' ->', + # llmemory.cast_ptr_to_adr(resultbox.getref_base())) + self.registers_r[target_index] = resultbox + elif resultbox.type == history.FLOAT: + self.registers_f[target_index] = resultbox + else: + raise AssertionError("bad result box type") # ------------------------------ - for _n in range(codewriter.MAX_MAKE_NEW_VARS): - _decl = ', '.join(["'box'" for _i in range(_n)]) - _allargs = ', '.join(["box%d" % _i for _i in range(_n)]) - exec py.code.Source(""" - @arguments(%s) - def opimpl_make_new_vars_%d(self, %s): - if not we_are_translated(): - check_args(%s) - self.env = [%s] - """ % (_decl, _n, _allargs, _allargs, _allargs)).compile() - - @arguments("varargs") - def opimpl_make_new_vars(self, newenv): - if not we_are_translated(): - check_args(*newenv) - self.env = newenv - for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod', 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', @@ -210,175 +175,241 @@ 'float_add', 'float_sub', 'float_mul', 'float_truediv', 'float_lt', 'float_le', 'float_eq', 'float_ne', 'float_gt', 'float_ge', + 'ptr_eq', 'ptr_ne', ]: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) + return self.execute(rop.%s, b1, b2) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) - return self.metainterp.handle_overflow_error() + self.metainterp.clear_exception() + resbox = self.execute(rop.%s, b1, b2) + self.make_result_of_lastop(resbox) # same as execute_varargs() + self.metainterp.handle_possible_overflow_error() + return resbox ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', - 'cast_ptr_to_int', 'cast_float_to_int', - 'cast_int_to_float', 'float_neg', 'float_abs', - 'float_is_true', + for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert', + 'cast_float_to_int', 'cast_int_to_float', + 'float_neg', 'float_abs', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, b) + return self.execute(rop.%s, b) ''' % (_opimpl, _opimpl.upper())).compile() - @arguments() - def opimpl_return(self): - assert len(self.env) == 1 - return self.metainterp.finishframe(self.env[0]) + @arguments("box") + def opimpl_ptr_nonzero(self, box): + return self.execute(rop.PTR_NE, box, history.CONST_NULL) + + @arguments("box") + def opimpl_ptr_iszero(self, box): + return self.execute(rop.PTR_EQ, box, history.CONST_NULL) + + @arguments("box") + def _opimpl_any_return(self, box): + self.metainterp.finishframe(box) + + opimpl_int_return = _opimpl_any_return + opimpl_ref_return = _opimpl_any_return + opimpl_float_return = _opimpl_any_return @arguments() def opimpl_void_return(self): - assert len(self.env) == 0 - return self.metainterp.finishframe(None) + self.metainterp.finishframe(None) + + @arguments("box") + def _opimpl_any_copy(self, box): + return box + + opimpl_int_copy = _opimpl_any_copy + opimpl_ref_copy = _opimpl_any_copy + opimpl_float_copy = _opimpl_any_copy + + @arguments("box") + def _opimpl_any_push(self, box): + self.pushed_box = box + + opimpl_int_push = _opimpl_any_push + opimpl_ref_push = _opimpl_any_push + opimpl_float_push = _opimpl_any_push - @arguments("jumptarget") + @arguments() + def _opimpl_any_pop(self): + box = self.pushed_box + self.pushed_box = None + return box + + opimpl_int_pop = _opimpl_any_pop + opimpl_ref_pop = _opimpl_any_pop + opimpl_float_pop = _opimpl_any_pop + + @arguments("label") + def opimpl_catch_exception(self, target): + """This is a no-op when run normally. We can check that + last_exc_value_box is None; it should have been set to None + by the previous instruction. If the previous instruction + raised instead, finishframe_exception() should have been + called and we would not be there.""" + assert self.metainterp.last_exc_value_box is None + + @arguments("label") def opimpl_goto(self, target): self.pc = target - @arguments("orgpc", "jumptarget", "box", "varargs") - def opimpl_goto_if_not(self, pc, target, box, livelist): + @arguments("box", "label") + def opimpl_goto_if_not(self, box, target): switchcase = box.getint() if switchcase: opnum = rop.GUARD_TRUE else: - self.pc = target opnum = rop.GUARD_FALSE - self.env = livelist - self.generate_guard(pc, opnum, box) - # note about handling self.env explicitly here: it is done in - # such a way that the 'box' on which we generate the guard is - # typically not included in the livelist. - - def follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - target = self.load_3byte() # load the 'target' argument - self.pc = target # jump - - def ignore_next_guard_nullness(self, opnum): - _op_ooisnull = self.metainterp.staticdata._op_ooisnull - _op_oononnull = self.metainterp.staticdata._op_oononnull - bc = ord(self.bytecode[self.pc]) - if bc == _op_ooisnull: - if opnum == rop.GUARD_ISNULL: - res = ConstInt(0) - else: - res = ConstInt(1) + self.generate_guard(opnum, box) + if not switchcase: + self.pc = target + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_true(self, box, target): + condbox = self.execute(rop.INT_IS_TRUE, box) + self.opimpl_goto_if_not(condbox, target) + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_zero(self, box, target): + condbox = self.execute(rop.INT_IS_ZERO, box) + self.opimpl_goto_if_not(condbox, target) + + for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', + 'ptr_eq', 'ptr_ne']: + exec py.code.Source(''' + @arguments("box", "box", "label") + def opimpl_goto_if_not_%s(self, b1, b2, target): + condbox = self.execute(rop.%s, b1, b2) + self.opimpl_goto_if_not(condbox, target) + ''' % (_opimpl, _opimpl.upper())).compile() + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL else: - assert bc == _op_oononnull - if opnum == rop.GUARD_ISNULL: - res = ConstInt(1) - else: - res = ConstInt(0) - self.pc += 1 # past the bytecode for ptr_iszero/ptr_nonzero - self.load_int() # past the 'box' argument - self.make_result_box(res) - - def dont_follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - self.load_3byte() # past the 'target' argument - self.load_int() # past the 'box' argument - self.ignore_varargs() # past the 'livelist' argument - - @arguments("orgpc", "box", "constargs", "jumptargets") - def opimpl_switch(self, pc, valuebox, constargs, jumptargets): - box = self.implement_guard_value(pc, valuebox) - for i in range(len(constargs)): - casebox = constargs[i] - if box.same_constant(casebox): - self.pc = jumptargets[i] - break - - @arguments("orgpc", "box", "constbox") - def opimpl_switch_dict(self, pc, valuebox, switchdict): - box = self.implement_guard_value(pc, valuebox) + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if not value: + self.pc = target + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL + else: + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if value: + self.pc = target + + @arguments("box", "descr", "orgpc") + def opimpl_switch(self, valuebox, switchdict, orgpc): + box = self.implement_guard_value(orgpc, valuebox) search_value = box.getint() - assert isinstance(switchdict, codewriter.SwitchDict) + assert isinstance(switchdict, SwitchDictDescr) try: self.pc = switchdict.dict[search_value] except KeyError: pass - @arguments("descr") - def opimpl_new(self, size): - self.execute_with_descr(rop.NEW, descr=size) - - @arguments("constbox") - def opimpl_new_with_vtable(self, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, vtablebox) + @arguments() + def opimpl_unreachable(self): + raise AssertionError("unreachable") - @arguments("box") - def opimpl_runtimenew(self, classbox): - self.execute(rop.RUNTIMENEW, classbox) + @arguments("descr") + def opimpl_new(self, sizedescr): + return self.execute_with_descr(rop.NEW, sizedescr) - @arguments("orgpc", "box", "descr") - def opimpl_instanceof(self, pc, objbox, typedescr): - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + @arguments("descr") + def opimpl_new_with_vtable(self, sizedescr): + cpu = self.metainterp.cpu + cls = heaptracker.descr2vtable(cpu, sizedescr) + return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls)) - @arguments("box", "box") - def opimpl_subclassof(self, box1, box2): - self.execute(rop.SUBCLASSOF, box1, box2) +## @FixME #arguments("box") +## def opimpl_runtimenew(self, classbox): +## self.execute(rop.RUNTIMENEW, classbox) + +## @FixME #arguments("orgpc", "box", "descr") +## def opimpl_instanceof(self, pc, objbox, typedescr): +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + +## @FixME #arguments("box", "box") +## def opimpl_subclassof(self, box1, box2): +## self.execute(rop.SUBCLASSOF, box1, box2) @arguments("descr", "box") - def opimpl_new_array(self, itemsize, countbox): - self.execute_with_descr(rop.NEW_ARRAY, itemsize, countbox) + def opimpl_new_array(self, itemsizedescr, countbox): + return self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, countbox) @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_pure_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_pure_i = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_r = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_f = _opimpl_getarrayitem_gc_pure_any @arguments("box", "descr", "box", "box") - def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydesc, arraybox, indexbox, itembox) + def _opimpl_setarrayitem_gc_any(self, arraybox, arraydescr, + indexbox, itembox): + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, itembox) + + opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any @arguments("box", "descr") - def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute_with_descr(rop.ARRAYLEN_GC, arraydesc, arraybox) + def opimpl_arraylen_gc(self, arraybox, arraydescr): + return self.execute_with_descr(rop.ARRAYLEN_GC, arraydescr, arraybox) @arguments("descr", "box", "box", "box", "box", "box", "box", "descr") def opimpl_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): + source_startbox, dest_startbox, lengthbox, + arraydescr): self.execute_with_descr(rop.ARRAYCOPY, arraydescr, calldescr, fnptr, sourcebox, destbox, source_startbox, dest_startbox, lengthbox) @arguments("orgpc", "box", "descr", "box") - def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): + def opimpl_check_neg_index(self, orgpc, arraybox, arraydescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, arraydesc, arraybox) + rop.ARRAYLEN_GC, arraydescr, arraybox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) + return indexbox @arguments("descr", "descr", "descr", "descr", "box") def opimpl_newlist(self, structdescr, lengthdescr, itemsdescr, arraydescr, @@ -390,131 +421,87 @@ sizebox) self.metainterp.execute_and_record(rop.SETFIELD_GC, itemsdescr, sbox, abox) - self.make_result_box(sbox) + return sbox @arguments("box", "descr", "descr", "box") - def opimpl_getlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox): + def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydescr, arraybox, indexbox) + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any @arguments("box", "descr", "descr", "box", "box") - def opimpl_setlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox, - valuebox): + def _opimpl_setlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox, valuebox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, indexbox, valuebox) + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, valuebox) + + opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any @arguments("orgpc", "box", "descr", "box") - def opimpl_check_resizable_neg_index(self, pc, listbox, lengthdesc, + def opimpl_check_resizable_neg_index(self, orgpc, listbox, lengthdescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.GETFIELD_GC, lengthdesc, listbox) + rop.GETFIELD_GC, lengthdescr, listbox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) - - @arguments("orgpc", "box") - def opimpl_check_zerodivisionerror(self, pc, box): - nonzerobox = self.metainterp.execute_and_record( - rop.INT_NE, None, box, ConstInt(0)) - nonzerobox = self.implement_guard_value(pc, nonzerobox) - if nonzerobox.getint(): - return False - else: - # division by zero! - return self.metainterp.raise_zero_division_error() - - @arguments("orgpc", "box", "box") - def opimpl_check_div_overflow(self, pc, box1, box2): - # detect the combination "box1 = -sys.maxint-1, box2 = -1". - import sys - tmp1 = self.metainterp.execute_and_record( # combination to detect: - rop.INT_ADD, None, box1, ConstInt(sys.maxint)) # tmp1=-1, box2=-1 - tmp2 = self.metainterp.execute_and_record( - rop.INT_AND, None, tmp1, box2) # tmp2=-1 - tmp3 = self.metainterp.execute_and_record( - rop.INT_EQ, None, tmp2, ConstInt(-1)) # tmp3? - tmp4 = self.implement_guard_value(pc, tmp3) # tmp4? - if not tmp4.getint(): - return False - else: - # division overflow! - return self.metainterp.raise_overflow_error() - - @arguments() - def opimpl_overflow_error(self): - return self.metainterp.raise_overflow_error() - - @arguments("orgpc", "box") - def opimpl_int_abs(self, pc, box): - nonneg = self.metainterp.execute_and_record( - rop.INT_GE, None, box, ConstInt(0)) - nonneg = self.implement_guard_value(pc, nonneg) - if nonneg.getint(): - self.make_result_box(box) - else: - self.execute(rop.INT_NEG, box) - - @arguments("orgpc", "box") - def opimpl_oononnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(1) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(0) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("orgpc", "box") - def opimpl_ooisnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(0) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(1) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("box", "box") - def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, box1, box2) - - @arguments("box", "box") - def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, box1, box2) - - opimpl_oois = opimpl_ptr_eq - opimpl_ooisnot = opimpl_ptr_ne + return indexbox @arguments("box", "descr") - def opimpl_getfield_gc(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC, fielddesc, box) + def _opimpl_getfield_gc_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) + opimpl_getfield_gc_i = _opimpl_getfield_gc_any + opimpl_getfield_gc_r = _opimpl_getfield_gc_any + opimpl_getfield_gc_f = _opimpl_getfield_gc_any + @arguments("box", "descr") - def opimpl_getfield_gc_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddesc, box) + def _opimpl_getfield_gc_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box) + opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_GC, fielddesc, box, valuebox) + def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) + opimpl_setfield_gc_i = _opimpl_setfield_gc_any + opimpl_setfield_gc_r = _opimpl_setfield_gc_any + opimpl_setfield_gc_f = _opimpl_setfield_gc_any @arguments("box", "descr") - def opimpl_getfield_raw(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW, fielddesc, box) + def _opimpl_getfield_raw_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box) + opimpl_getfield_raw_i = _opimpl_getfield_raw_any + opimpl_getfield_raw_r = _opimpl_getfield_raw_any + opimpl_getfield_raw_f = _opimpl_getfield_raw_any + @arguments("box", "descr") - def opimpl_getfield_raw_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddesc, box) + def _opimpl_getfield_raw_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box) + opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_RAW, fielddesc, box, valuebox) + def _opimpl_setfield_raw_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox) + opimpl_setfield_raw_i = _opimpl_setfield_raw_any + opimpl_setfield_raw_r = _opimpl_setfield_raw_any + opimpl_setfield_raw_f = _opimpl_setfield_raw_any def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable @@ -522,7 +509,7 @@ standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False - eqbox = self.metainterp.execute_and_record(rop.OOIS, None, + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, box, standard_box) eqbox = self.implement_guard_value(pc, eqbox) isstandard = eqbox.getint() @@ -530,9 +517,9 @@ self.metainterp.replace_box(box, standard_box) return not isstandard - def _get_virtualizable_field_descr(self, index): + def _get_virtualizable_field_index(self, fielddescr): vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.static_field_descrs[index] + return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): vinfo = self.metainterp.staticdata.virtualizable_info @@ -542,328 +529,271 @@ vinfo = self.metainterp.staticdata.virtualizable_info return vinfo.array_descrs[index] - @arguments("orgpc", "box", "int") - def opimpl_getfield_vable(self, pc, basebox, index): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.GETFIELD_GC, self._get_virtualizable_field_descr(index), basebox) - return + @arguments("orgpc", "box", "descr") + def _opimpl_getfield_vable(self, pc, box, fielddescr): + if self._nonstandard_virtualizable(pc, box): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) self.metainterp.check_synchronized_virtualizable() - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box") - def opimpl_setfield_vable(self, pc, basebox, index, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.SETFIELD_GC, self._get_virtualizable_field_descr(index), basebox, valuebox) + index = self._get_virtualizable_field_index(fielddescr) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getfield_vable_i = _opimpl_getfield_vable + opimpl_getfield_vable_r = _opimpl_getfield_vable + opimpl_getfield_vable_f = _opimpl_getfield_vable + + @arguments("orgpc", "box", "descr", "box") + def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox): + if self._nonstandard_virtualizable(pc, box): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) return + index = self._get_virtualizable_field_index(fielddescr) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - def _get_arrayitem_vable_index(self, pc, arrayindex, indexbox): + opimpl_setfield_vable_i = _opimpl_setfield_vable + opimpl_setfield_vable_r = _opimpl_setfield_vable + opimpl_setfield_vable_f = _opimpl_setfield_vable + + def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] index = indexbox.getint() if index < 0: index += vinfo.get_array_length(virtualizable, arrayindex) assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex) return vinfo.get_index_in_array(virtualizable, arrayindex, index) - @arguments("orgpc", "box", "int", "box") - def opimpl_getarrayitem_vable(self, pc, basebox, arrayindex, indexbox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + @arguments("orgpc", "box", "descr", "descr", "box") + def _opimpl_getarrayitem_vable(self, pc, box, fdescr, adescr, indexbox): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.GETARRAYITEM_GC, descr, - arraybox, indexbox) - return + fdescr, box) + return self.execute_with_descr(rop.GETARRAYITEM_GC, adescr, + arraybox, indexbox) self.metainterp.check_synchronized_virtualizable() - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box", "box") - def opimpl_setarrayitem_vable(self, pc, basebox, arrayindex, indexbox, + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr", "box", "box") + def _opimpl_setarrayitem_vable(self, pc, box, fdescr, adescr, indexbox, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.SETARRAYITEM_GC, descr, + fdescr, box) + self.execute_with_descr(rop.SETARRAYITEM_GC, adescr, arraybox, indexbox, valuebox) return - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - @arguments("orgpc", "box", "int") - def opimpl_arraylen_vable(self, pc, basebox, arrayindex): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + + opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr") + def opimpl_arraylen_vable(self, pc, box, fdescr, adescr): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.ARRAYLEN_GC, descr, arraybox) - return + fdescr, box) + return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[fdescr] result = vinfo.get_array_length(virtualizable, arrayindex) - self.make_result_box(ConstInt(result)) + return ConstInt(result) - def perform_call(self, jitcode, varargs, greenkey=None): - if (self.metainterp.is_blackholing() and - jitcode.calldescr is not None): - # when producing only a BlackHole, we can implement this by - # calling the subfunction directly instead of interpreting it - if jitcode.cfnptr is not None: - # for non-oosends - varargs = [jitcode.cfnptr] + varargs - res = self.execute_varargs(rop.CALL, varargs, - descr=jitcode.calldescr, exc=True) - else: - # for oosends (ootype only): calldescr is a MethDescr - res = self.execute_varargs(rop.OOSEND, varargs, - descr=jitcode.calldescr, exc=True) - self.metainterp.load_fields_from_virtualizable() - return res - else: - # when tracing, this bytecode causes the subfunction to be entered - f = self.metainterp.newframe(jitcode, greenkey) - f.setup_call(varargs) - return True - - @arguments("bytecode", "varargs") - def opimpl_call(self, callee, varargs): - return self.perform_call(callee, varargs) - - @arguments("descr", "varargs") - def opimpl_residual_call(self, calldescr, varargs): - return self.do_residual_call(varargs, descr=calldescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_call_loopinvariant(self, calldescr, varargs): - return self.execute_varargs(rop.CALL_LOOPINVARIANT, varargs, calldescr, exc=True) - - @arguments("orgpc", "descr", "varargs") - def opimpl_recursive_call(self, pc, calldescr, varargs): - warmrunnerstate = self.metainterp.staticdata.state + @arguments("jitcode", "boxes") + def _opimpl_inline_call1(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes2") + def _opimpl_inline_call2(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes3") + def _opimpl_inline_call3(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + + opimpl_inline_call_r_i = _opimpl_inline_call1 + opimpl_inline_call_r_r = _opimpl_inline_call1 + opimpl_inline_call_r_v = _opimpl_inline_call1 + opimpl_inline_call_ir_i = _opimpl_inline_call2 + opimpl_inline_call_ir_r = _opimpl_inline_call2 + opimpl_inline_call_ir_v = _opimpl_inline_call2 + opimpl_inline_call_irf_i = _opimpl_inline_call3 + opimpl_inline_call_irf_r = _opimpl_inline_call3 + opimpl_inline_call_irf_f = _opimpl_inline_call3 + opimpl_inline_call_irf_v = _opimpl_inline_call3 + + @arguments("box", "descr", "boxes") + def _opimpl_residual_call1(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes2") + def _opimpl_residual_call2(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes3") + def _opimpl_residual_call3(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + + opimpl_residual_call_r_i = _opimpl_residual_call1 + opimpl_residual_call_r_r = _opimpl_residual_call1 + opimpl_residual_call_r_v = _opimpl_residual_call1 + opimpl_residual_call_ir_i = _opimpl_residual_call2 + opimpl_residual_call_ir_r = _opimpl_residual_call2 + opimpl_residual_call_ir_v = _opimpl_residual_call2 + opimpl_residual_call_irf_i = _opimpl_residual_call3 + opimpl_residual_call_irf_r = _opimpl_residual_call3 + opimpl_residual_call_irf_f = _opimpl_residual_call3 + opimpl_residual_call_irf_v = _opimpl_residual_call3 + + @arguments("boxes3", "boxes3") + def _opimpl_recursive_call(self, greenboxes, redboxes): + allboxes = greenboxes + redboxes + metainterp_sd = self.metainterp.staticdata + portal_code = metainterp_sd.portal_code + warmrunnerstate = metainterp_sd.state token = None - if not self.metainterp.is_blackholing() and warmrunnerstate.inlining: - num_green_args = self.metainterp.staticdata.num_green_args - portal_code = self.metainterp.staticdata.portal_code - greenkey = varargs[1:num_green_args + 1] - if warmrunnerstate.can_inline_callable(greenkey): - return self.perform_call(portal_code, varargs[1:], greenkey) - token = warmrunnerstate.get_assembler_token(greenkey) - call_position = 0 - if token is not None: - call_position = len(self.metainterp.history.operations) + if warmrunnerstate.inlining: + if warmrunnerstate.can_inline_callable(greenboxes): + return self.metainterp.perform_call(portal_code, allboxes, + greenkey=greenboxes) + token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - greenargs = varargs[1:num_green_args + 1] - self.verify_green_args(greenargs) - res = self.do_residual_call(varargs, descr=calldescr, exc=True) - if not self.metainterp.is_blackholing() and token is not None: - # XXX fix the call position, - found = False - while True: - op = self.metainterp.history.operations[call_position] - if op.opnum == rop.CALL or op.opnum == rop.CALL_MAY_FORCE: - found = True - break - call_position += 1 - assert found - # - # this will substitute the residual call with assembler call - self.metainterp.direct_assembler_call(pc, varargs, token, - call_position) - return res - - @arguments("descr", "varargs") - def opimpl_residual_call_noexception(self, calldescr, varargs): - self.do_residual_call(varargs, descr=calldescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_call_pure(self, calldescr, varargs): - self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False) - - @arguments("orgpc", "descr", "box", "varargs") - def opimpl_indirect_call(self, pc, calldescr, box, varargs): - box = self.implement_guard_value(pc, box) - cpu = self.metainterp.cpu - key = cpu.ts.getaddr_for_box(cpu, box) - jitcode = self.metainterp.staticdata.bytecode_for_address(key) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.do_residual_call([box] + varargs, - descr=calldescr, exc=True) - - @arguments("orgpc", "methdescr", "varargs") - def opimpl_oosend(self, pc, methdescr, varargs): - objbox = varargs[0] - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - oocls = clsbox.getref(ootype.Class) - jitcode = methdescr.get_jitcode_for_class(oocls) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.execute_varargs(rop.OOSEND, varargs, - descr=methdescr, exc=True) + self.verify_green_args(greenboxes) + # + k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + funcbox = ConstInt(heaptracker.adr2int(k)) + return self.do_residual_call(funcbox, portal_code.calldescr, + allboxes, assembler_call_token=token) + + opimpl_recursive_call_i = _opimpl_recursive_call + opimpl_recursive_call_r = _opimpl_recursive_call + opimpl_recursive_call_f = _opimpl_recursive_call + opimpl_recursive_call_v = _opimpl_recursive_call + +## @FixME #arguments("orgpc", "methdescr", "varargs") +## def opimpl_oosend(self, pc, methdescr, varargs): +## objbox = varargs[0] +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## oocls = clsbox.getref(ootype.Class) +## jitcode = methdescr.get_jitcode_for_class(oocls) +## if jitcode is not None: +## # we should follow calls to this graph +## return self.perform_call(jitcode, varargs) +## else: +## # but we should not follow calls to that graph +## return self.execute_varargs(rop.OOSEND, varargs, +## descr=methdescr, exc=True) @arguments("box") - def opimpl_strlen(self, str): - self.execute(rop.STRLEN, str) + def opimpl_strlen(self, strbox): + return self.execute(rop.STRLEN, strbox) @arguments("box") - def opimpl_unicodelen(self, str): - self.execute(rop.UNICODELEN, str) + def opimpl_unicodelen(self, unicodebox): + return self.execute(rop.UNICODELEN, unicodebox) @arguments("box", "box") - def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, str, index) + def opimpl_strgetitem(self, strbox, indexbox): + return self.execute(rop.STRGETITEM, strbox, indexbox) @arguments("box", "box") - def opimpl_unicodegetitem(self, str, index): - self.execute(rop.UNICODEGETITEM, str, index) + def opimpl_unicodegetitem(self, unicodebox, indexbox): + return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox) @arguments("box", "box", "box") - def opimpl_strsetitem(self, str, index, newchar): - self.execute(rop.STRSETITEM, str, index, newchar) + def opimpl_strsetitem(self, strbox, indexbox, newcharbox): + return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox) @arguments("box", "box", "box") - def opimpl_unicodesetitem(self, str, index, newchar): - self.execute(rop.UNICODESETITEM, str, index, newchar) + def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox): + self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox) @arguments("box") - def opimpl_newstr(self, length): - self.execute(rop.NEWSTR, length) + def opimpl_newstr(self, lengthbox): + return self.execute(rop.NEWSTR, lengthbox) @arguments("box") - def opimpl_newunicode(self, length): - self.execute(rop.NEWUNICODE, length) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_canraise(self, methdescr, varargs): - return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_noraise(self, methdescr, varargs): - self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_pure(self, methdescr, boxes): - self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, exc=False) + def opimpl_newunicode(self, lengthbox): + return self.execute(rop.NEWUNICODE, lengthbox) - @arguments("orgpc", "box") - def opimpl_guard_value(self, pc, box): - constbox = self.implement_guard_value(pc, box) - self.make_result_box(constbox) - - @arguments("orgpc", "int") - def opimpl_guard_green(self, pc, boxindex): - """Like guard_value, but overwrites the original box with the const. - Used to prevent Boxes from showing up in the greenkey of some - operations, like jit_merge_point. The in-place overwriting is - convenient for jit_merge_point, which expects self.env to contain - not more than the greens+reds described in the jitdriver.""" - box = self.env[boxindex] - constbox = self.implement_guard_value(pc, box) - self.env[boxindex] = constbox +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_canraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=True) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_noraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=False) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_pure(self, methdescr, boxes): +## return self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, +## exc=False) + + @arguments("orgpc", "box",) + def _opimpl_guard_value(self, orgpc, box): + self.implement_guard_value(orgpc, box) + + opimpl_int_guard_value = _opimpl_guard_value + opimpl_ref_guard_value = _opimpl_guard_value + opimpl_float_guard_value = _opimpl_guard_value @arguments("orgpc", "box") - def opimpl_guard_class(self, pc, box): + def opimpl_guard_class(self, orgpc, box): clsbox = self.cls_of_box(box) - if isinstance(box, Box): - self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) - self.make_result_box(clsbox) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_builtin(self, pc, box, builtin): -## self.generate_guard(pc, "guard_builtin", box, [builtin]) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_len(self, pc, box, builtin): -## intbox = self.metainterp.cpu.execute_operation( -## 'len', [builtin.len_func, box], 'int') -## self.generate_guard(pc, "guard_len", box, [intbox]) - - @arguments("box") - def opimpl_keepalive(self, box): - pass # xxx? - - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args - for i in range(num_green_args): - assert isinstance(varargs[i], Const) - - def blackhole_reached_merge_point(self, varargs): - if self.metainterp.in_recursion: - portal_code = self.metainterp.staticdata.portal_code - # small hack: fish for the result box - lenenv = len(self.env) - raised = self.perform_call(portal_code, varargs) - # in general this cannot be assumed, but when blackholing, - # perform_call returns True only if an exception is called. In - # this case perform_call has called finishframe_exception - # already, so we need to return. - if raised: - return - if lenenv == len(self.env): - res = None - else: - assert lenenv == len(self.env) - 1 - res = self.env.pop() - self.metainterp.finishframe(res) - else: - raise self.metainterp.staticdata.ContinueRunningNormally(varargs) + self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + return clsbox @arguments() def opimpl_can_enter_jit(self): - # Note: when running with a BlackHole history, this 'can_enter_jit' - # may be completely skipped by the logic that replaces perform_call - # with rop.CALL. But in that case, no-one will check the flag anyway, - # so it's fine. if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - @arguments() - def opimpl_jit_merge_point(self): - if not self.metainterp.is_blackholing(): - self.verify_green_args(self.env) - # xxx we may disable the following line in some context later - self.debug_merge_point() - if self.metainterp.seen_can_enter_jit: - self.metainterp.seen_can_enter_jit = False - assert not self.metainterp.in_recursion - # ^^^ it's impossible to arrive here with in_recursion set - # to a non-zero value: seen_can_enter_jit can only be set - # to True by opimpl_can_enter_jit, which should be executed - # just before opimpl_jit_merge_point (no recursion inbetween). - try: - self.metainterp.reached_can_enter_jit(self.env) - except GiveUp: - self.metainterp.switch_to_blackhole(ABORT_BRIDGE) - if self.metainterp.is_blackholing(): - self.blackhole_reached_merge_point(self.env) - return True + def verify_green_args(self, varargs): + num_green_args = self.metainterp.staticdata.num_green_args + assert len(varargs) == num_green_args + for i in range(num_green_args): + assert isinstance(varargs[i], Const) - def debug_merge_point(self): + @arguments("orgpc", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): + self.verify_green_args(greenboxes) + # xxx we may disable the following line in some context later + self.debug_merge_point(greenboxes) + if self.metainterp.seen_can_enter_jit: + self.metainterp.seen_can_enter_jit = False + # Assert that it's impossible to arrive here with in_recursion + # set to a non-zero value: seen_can_enter_jit can only be set + # to True by opimpl_can_enter_jit, which should be executed + # just before opimpl_jit_merge_point (no recursion inbetween). + assert not self.metainterp.in_recursion + # Set self.pc to point to jit_merge_point instead of just after: + # if reached_can_enter_jit() raises SwitchToBlackhole, then the + # pc is still at the jit_merge_point, which is a point that is + # much less expensive to blackhole out of. + saved_pc = self.pc + self.pc = orgpc + self.metainterp.reached_can_enter_jit(greenboxes, redboxes) + self.pc = saved_pc + + def debug_merge_point(self, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - num_green_args = self.metainterp.staticdata.num_green_args - greenkey = self.env[:num_green_args] sd = self.metainterp.staticdata loc = sd.state.get_location_str(greenkey) debug_print(loc) @@ -871,45 +801,45 @@ self.metainterp.history.record(rop.DEBUG_MERGE_POINT, [constloc], None) - @arguments("jumptarget") - def opimpl_setup_exception_block(self, exception_target): - self.exception_target = exception_target - - @arguments() - def opimpl_teardown_exception_block(self): - self.exception_target = -1 - - @arguments("constbox", "jumptarget", "orgpc") - def opimpl_goto_if_exception_mismatch(self, vtableref, next_exc_target, pc): - # XXX used to be: - # assert isinstance(self.exception_box, Const) # XXX - # seems this can happen that self.exception_box is not a Const, - # but I failed to write a test so far :-( - self.exception_box = self.implement_guard_value(pc, self.exception_box) - cpu = self.metainterp.cpu - ts = self.metainterp.cpu.ts - if not ts.subclassOf(cpu, self.exception_box, vtableref): + @arguments("box", "label") + def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target): + metainterp = self.metainterp + last_exc_value_box = metainterp.last_exc_value_box + assert last_exc_value_box is not None + assert metainterp.class_of_last_exc_is_const + if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox): self.pc = next_exc_target - @arguments("int") - def opimpl_put_last_exception(self, index): - assert index >= 0 - self.env.insert(index, self.exception_box) - - @arguments("int") - def opimpl_put_last_exc_value(self, index): - assert index >= 0 - self.env.insert(index, self.exc_value_box) + @arguments("orgpc", "box") + def opimpl_raise(self, orgpc, exc_value_box): + # xxx hack + clsbox = self.cls_of_box(exc_value_box) + self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + resumepc=orgpc) + self.metainterp.class_of_last_exc_is_const = True + self.metainterp.last_exc_value_box = exc_value_box + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_raise(self): - assert len(self.env) == 2 - return self.metainterp.finishframe_exception(self.env[0], self.env[1]) + def opimpl_reraise(self): + assert self.metainterp.last_exc_value_box is not None + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_reraise(self): - return self.metainterp.finishframe_exception(self.exception_box, - self.exc_value_box) + def opimpl_last_exception(self): + # Same comment as in opimpl_goto_if_exception_mismatch(). + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + assert self.metainterp.class_of_last_exc_is_const + return self.metainterp.cpu.ts.cls_of_box(exc_value_box) + + @arguments() + def opimpl_last_exc_value(self): + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + return exc_value_box @arguments("box") def opimpl_virtual_ref(self, box): @@ -920,30 +850,26 @@ # the 'virtual_ref(frame)'). # # * if we detect that the virtual box escapes during tracing - # already (by generating a CALl_MAY_FORCE that marks the flags + # already (by generating a CALL_MAY_FORCE that marks the flags # in the vref), then we replace the vref in the list with # ConstPtr(NULL). # metainterp = self.metainterp - if metainterp.is_blackholing(): - resbox = box # good enough when blackholing - else: - vrefinfo = metainterp.staticdata.virtualref_info - obj = box.getref_base() - vref = vrefinfo.virtual_ref_during_tracing(obj) - resbox = history.BoxPtr(vref) - cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) - metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) - # Note: we allocate a JIT_VIRTUAL_REF here - # (in virtual_ref_during_tracing()), in order to detect when - # the virtual escapes during tracing already. We record it as a - # VIRTUAL_REF operation, although the backend sees this operation - # as a no-op. The point is that the backend should not really see - # it in practice, as optimizeopt.py should either kill it or - # replace it with a NEW_WITH_VTABLE followed by SETFIELD_GCs. + vrefinfo = metainterp.staticdata.virtualref_info + obj = box.getref_base() + vref = vrefinfo.virtual_ref_during_tracing(obj) + resbox = history.BoxPtr(vref) + cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) + metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) + # Note: we allocate a JIT_VIRTUAL_REF here + # (in virtual_ref_during_tracing()), in order to detect when + # the virtual escapes during tracing already. We record it as a + # VIRTUAL_REF operation. Later, optimizeopt.py should either kill + # that operation or replace it with a NEW_WITH_VTABLE followed by + # SETFIELD_GCs. metainterp.virtualref_boxes.append(box) metainterp.virtualref_boxes.append(resbox) - self.make_result_box(resbox) + return resbox @arguments("box") def opimpl_virtual_ref_finish(self, box): @@ -953,27 +879,32 @@ vrefbox = metainterp.virtualref_boxes.pop() lastbox = metainterp.virtualref_boxes.pop() assert box.getref_base() == lastbox.getref_base() - if not metainterp.is_blackholing(): - vrefinfo = metainterp.staticdata.virtualref_info - vref = vrefbox.getref_base() - if vrefinfo.is_virtual_ref(vref): - metainterp.history.record(rop.VIRTUAL_REF_FINISH, - [vrefbox, lastbox], None) + vrefinfo = metainterp.staticdata.virtualref_info + vref = vrefbox.getref_base() + if vrefinfo.is_virtual_ref(vref): + metainterp.history.record(rop.VIRTUAL_REF_FINISH, + [vrefbox, lastbox], None) # ------------------------------ def setup_call(self, argboxes): - if not we_are_translated(): - check_args(*argboxes) self.pc = 0 - self.env = argboxes + count_i = count_r = count_f = 0 + for box in argboxes: + if box.type == history.INT: + self.registers_i[count_i] = box + count_i += 1 + elif box.type == history.REF: + self.registers_r[count_r] = box + count_r += 1 + elif box.type == history.FLOAT: + self.registers_f[count_f] = box + count_f += 1 + else: + raise AssertionError(box.type) - def setup_resume_at_op(self, pc, exception_target, env): - if not we_are_translated(): - check_args(*env) + def setup_resume_at_op(self, pc): self.pc = pc - self.exception_target = exception_target - self.env = env ## values = ' '.join([box.repr_rpython() for box in self.env]) ## log('setup_resume_at_op %s:%d [%s] %d' % (self.jitcode.name, ## self.pc, values, @@ -984,25 +915,21 @@ # whenever the 'opcode_implementations' (which is one of the 'opimpl_' # methods) returns True. This is the case when the current frame # changes, due to a call or a return. - while True: - pc = self.pc - op = ord(self.bytecode[pc]) - #print self.metainterp.opcode_names[op] - self.pc = pc + 1 + try: staticdata = self.metainterp.staticdata - stop = staticdata.opcode_implementations[op](self, pc) - #self.metainterp.most_recent_mp = None - if stop: - break + while True: + pc = self.pc + op = ord(self.bytecode[pc]) + #debug_print(self.jitcode.name, pc) + #print staticdata.opcode_names[op] + staticdata.opcode_implementations[op](self, pc) + except ChangeFrame: + pass - def generate_guard(self, pc, opnum, box, extraargs=[]): + def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): if isinstance(box, Const): # no need for a guard return metainterp = self.metainterp - if metainterp.is_blackholing(): - return - saved_pc = self.pc - self.pc = pc if box is not None: moreargs = [box] + extraargs else: @@ -1020,15 +947,18 @@ virtualizable_boxes = None if metainterp.staticdata.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes + saved_pc = self.pc + if resumepc >= 0: + self.pc = resumepc resume.capture_resumedata(metainterp.framestack, virtualizable_boxes, metainterp.virtualref_boxes, resumedescr) + self.pc = saved_pc self.metainterp.staticdata.profiler.count_ops(opnum, GUARDS) # count metainterp.attach_debug_info(guard_op) - self.pc = saved_pc return guard_op - def implement_guard_value(self, pc, box): + def implement_guard_value(self, orgpc, box): """Promote the given Box into a Const. Note: be careful, it's a bit unclear what occurs if a single opcode needs to generate several ones and/or ones not near the beginning.""" @@ -1036,91 +966,138 @@ return box # no promotion needed, already a Const else: promoted_box = box.constbox() - self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box]) + self.generate_guard(rop.GUARD_VALUE, box, [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, promoted_box) return promoted_box def cls_of_box(self, box): - return self.metainterp.cpu.ts.cls_of_box(self.metainterp.cpu, box) + return self.metainterp.cpu.ts.cls_of_box(box) @specialize.arg(1) def execute(self, opnum, *argboxes): - self.execute_with_descr(opnum, None, *argboxes) + return self.metainterp.execute_and_record(opnum, None, *argboxes) @specialize.arg(1) def execute_with_descr(self, opnum, descr, *argboxes): - resbox = self.metainterp.execute_and_record(opnum, descr, *argboxes) - if resbox is not None: - self.make_result_box(resbox) + return self.metainterp.execute_and_record(opnum, descr, *argboxes) @specialize.arg(1) def execute_varargs(self, opnum, argboxes, descr, exc): + self.metainterp.clear_exception() resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes, descr=descr) - if resbox is not None: - self.make_result_box(resbox) + self.make_result_of_lastop(resbox) + # ^^^ this is done before handle_possible_exception() because we need + # the box to show up in get_list_of_active_boxes() if exc: - return self.metainterp.handle_exception() + self.metainterp.handle_possible_exception() else: - return self.metainterp.assert_no_exception() + self.metainterp.assert_no_exception() + return resbox - def do_residual_call(self, argboxes, descr, exc): + def do_residual_call(self, funcbox, descr, argboxes, + assembler_call_token=None): + # First build allboxes: it may need some reordering from the + # list provided in argboxes, depending on the order in which + # the arguments are expected by the function + allboxes = [None] * (len(argboxes)+1) + allboxes[0] = funcbox + src_i = src_r = src_f = 0 + i = 1 + for kind in descr.get_arg_types(): + if kind == history.INT: + while True: + box = argboxes[src_i] + src_i += 1 + if box.type == history.INT: + break + elif kind == history.REF: + while True: + box = argboxes[src_r] + src_r += 1 + if box.type == history.REF: + break + elif kind == history.FLOAT: + while True: + box = argboxes[src_f] + src_f += 1 + if box.type == history.FLOAT: + break + else: + raise AssertionError + allboxes[i] = box + i += 1 + assert i == len(allboxes) + # effectinfo = descr.get_extra_info() - if effectinfo is None or effectinfo.forces_virtual_or_virtualizable: + if (effectinfo is None or + effectinfo.extraeffect == + effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE or + assembler_call_token is not None): # residual calls require attention to keep virtualizables in-sync + self.metainterp.clear_exception() self.metainterp.vable_and_vrefs_before_residual_call() - # xxx do something about code duplication resbox = self.metainterp.execute_and_record_varargs( - rop.CALL_MAY_FORCE, argboxes, descr=descr) - self.metainterp.vable_and_vrefs_after_residual_call() + rop.CALL_MAY_FORCE, allboxes, descr=descr) + self.metainterp.vrefs_after_residual_call() + if assembler_call_token is not None: + self.metainterp.direct_assembler_call(assembler_call_token) if resbox is not None: - self.make_result_box(resbox) - self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, []) - if exc: - return self.metainterp.handle_exception() + self.make_result_of_lastop(resbox) + self.metainterp.vable_after_residual_call() + self.generate_guard(rop.GUARD_NOT_FORCED, None) + self.metainterp.handle_possible_exception() + return resbox + else: + effect = effectinfo.extraeffect + if effect == effectinfo.EF_CANNOT_RAISE: + return self.execute_varargs(rop.CALL, allboxes, descr, False) + elif effect == effectinfo.EF_PURE: + return self.execute_varargs(rop.CALL_PURE, allboxes, + descr, False) + elif effect == effectinfo.EF_LOOPINVARIANT: + return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes, + descr, True) else: - return self.metainterp.assert_no_exception() + return self.execute_varargs(rop.CALL, allboxes, descr, True) + + def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes): + """The 'residual_call' operation is emitted in two cases: + when we have to generate a residual CALL operation, but also + to handle an indirect_call that may need to be inlined.""" + assert isinstance(funcbox, Const) + sd = self.metainterp.staticdata + key = sd.cpu.ts.getaddr_for_box(funcbox) + jitcode = sd.bytecode_for_address(key) + if jitcode is not None: + # we should follow calls to this graph + return self.metainterp.perform_call(jitcode, argboxes) else: - return self.execute_varargs(rop.CALL, argboxes, descr, exc) + # but we should not follow calls to that graph + return self.do_residual_call(funcbox, calldescr, argboxes) # ____________________________________________________________ class MetaInterpStaticData(object): - virtualizable_info = None logger_noopt = None logger_ops = None - def __init__(self, portal_graph, cpu, stats, options, + def __init__(self, cpu, options, ProfilerClass=EmptyProfiler, warmrunnerdesc=None): self.cpu = cpu - self.stats = stats + self.stats = self.cpu.stats self.options = options self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) - RESULT = portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) - - self.opcode_implementations = [] - self.opcode_names = [] - self.opname_to_index = {} - self.profiler = ProfilerClass() - - self.indirectcall_keys = [] - self.indirectcall_values = [] - self.warmrunnerdesc = warmrunnerdesc - self._op_goto_if_not = self.find_opcode('goto_if_not') - self._op_ooisnull = self.find_opcode('ooisnull') - self._op_oononnull = self.find_opcode('oononnull') backendmodule = self.cpu.__module__ backendmodule = backendmodule.split('.')[-2] self.jit_starting_line = 'JIT starting (%s)' % backendmodule - self.portal_code = None - self._class_sizes = None self._addr2name_keys = [] self._addr2name_values = [] @@ -1132,15 +1109,44 @@ def _freeze_(self): return True - def info_from_codewriter(self, portal_code, class_sizes, - list_of_addr2name, portal_runner_ptr): - self.portal_code = portal_code - self._class_sizes = class_sizes - self._addr2name_keys = [key for key, value in list_of_addr2name] + def setup_insns(self, insns): + self.opcode_names = ['?'] * len(insns) + self.opcode_implementations = [None] * len(insns) + for key, value in insns.items(): + assert self.opcode_implementations[value] is None + self.opcode_names[value] = key + name, argcodes = key.split('/') + opimpl = _get_opimpl_method(name, argcodes) + self.opcode_implementations[value] = opimpl + self.op_catch_exception = insns.get('catch_exception/L', -1) + + def setup_descrs(self, descrs): + self.opcode_descrs = descrs + + def setup_indirectcalltargets(self, indirectcalltargets): + self.indirectcalltargets = list(indirectcalltargets) + + def setup_list_of_addr2name(self, list_of_addr2name): + self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] - self._portal_runner_ptr = portal_runner_ptr - def finish_setup(self, optimizer=None): + def finish_setup(self, codewriter, optimizer=None): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) + # + asm = codewriter.assembler + self.setup_insns(asm.insns) + self.setup_descrs(asm.descrs) + self.setup_indirectcalltargets(asm.indirectcalltargets) + self.setup_list_of_addr2name(asm.list_of_addr2name) + # + self.portal_code = codewriter.mainjitcode + self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.virtualref_info = codewriter.callcontrol.virtualref_info + self.virtualizable_info = codewriter.callcontrol.virtualizable_info + RESULT = codewriter.portal_graph.getreturnvar().concretetype + self.result_type = history.getkind(RESULT) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args @@ -1156,20 +1162,12 @@ """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: debug_print(self.jit_starting_line) - self._setup_class_sizes() self.cpu.setup_once() if not self.profiler.initialized: self.profiler.start() self.profiler.initialized = True self.globaldata.initialized = True - def _setup_class_sizes(self): - class_sizes = {} - for vtable, sizedescr in self._class_sizes: - vtable = self.cpu.ts.cast_vtable_to_hashable(self.cpu, vtable) - class_sizes[vtable] = sizedescr - self.cpu.set_class_sizes(class_sizes) - def get_name_from_address(self, addr): # for debugging only if we_are_translated(): @@ -1200,39 +1198,16 @@ # because the keys are function addresses, so they # can change from run to run. d = {} - keys = self.indirectcall_keys - values = self.indirectcall_values - for i in range(len(keys)): - d[keys[i]] = values[i] + for jitcode in self.indirectcalltargets: + d[jitcode.fnaddr] = jitcode self.globaldata.indirectcall_dict = d return d.get(fnaddress, None) else: - for i in range(len(self.indirectcall_keys)): - if fnaddress == self.indirectcall_keys[i]: - return self.indirectcall_values[i] + for jitcode in self.indirectcalltargets: + if jitcode.fnaddr == fnaddress: + return jitcode return None - # ---------- construction-time interface ---------- - - def _register_indirect_call_target(self, fnaddress, jitcode): - self.indirectcall_keys.append(fnaddress) - self.indirectcall_values.append(jitcode) - - def find_opcode(self, name): - try: - return self.opname_to_index[name] - except KeyError: - self._register_opcode(name) - return self.opname_to_index[name] - - def _register_opcode(self, opname): - assert len(self.opcode_implementations) < 256, \ - "too many implementations of opcodes!" - name = "opimpl_" + opname - self.opname_to_index[opname] = len(self.opcode_implementations) - self.opcode_names.append(opname) - self.opcode_implementations.append(getattr(MIFrame, name).im_func) - # ---------------- logging ------------------------ def log(self, msg): @@ -1259,6 +1234,7 @@ self.addr2name = None self.loopnumbering = 0 self.resume_virtuals = {} + self.resume_virtuals_not_translated = [] # state = staticdata.state if state is not None: @@ -1283,23 +1259,32 @@ class MetaInterp(object): in_recursion = 0 - _already_allocated_resume_virtuals = None def __init__(self, staticdata): self.staticdata = staticdata self.cpu = staticdata.cpu self.portal_trace_positions = [] + self.free_frames_list = [] + self.last_exc_value_box = None - def is_blackholing(self): - return self.history is None + def perform_call(self, jitcode, boxes, greenkey=None): + # causes the metainterp to enter the given subfunction + # with a special case for recursive portal calls + f = self.newframe(jitcode, greenkey) + f.setup_call(boxes) + raise ChangeFrame def newframe(self, jitcode, greenkey=None): if jitcode is self.staticdata.portal_code: self.in_recursion += 1 - if greenkey is not None and not self.is_blackholing(): + if greenkey is not None: self.portal_trace_positions.append( (greenkey, len(self.history.operations))) - f = MIFrame(self, jitcode, greenkey) + if len(self.free_frames_list) > 0: + f = self.free_frames_list.pop() + else: + f = MIFrame(self) + f.setup(jitcode, greenkey) self.framestack.append(f) return f @@ -1307,23 +1292,27 @@ frame = self.framestack.pop() if frame.jitcode is self.staticdata.portal_code: self.in_recursion -= 1 - if frame.greenkey is not None and not self.is_blackholing(): + if frame.greenkey is not None: self.portal_trace_positions.append( (None, len(self.history.operations))) - return frame + # we save the freed MIFrames to avoid needing to re-create new + # MIFrame objects all the time; they are a bit big, with their + # 3*256 register entries. + frame.cleanup_registers() + self.free_frames_list.append(frame) def finishframe(self, resultbox): - frame = self.popframe() + # handle a non-exceptional return from the current frame + self.last_exc_value_box = None + self.popframe() if self.framestack: - if resultbox is not None: - self.framestack[-1].make_result_box(resultbox) - return True + self.framestack[-1].make_result_of_lastop(resultbox) + raise ChangeFrame else: - if not self.is_blackholing(): - try: - self.compile_done_with_this_frame(resultbox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_done_with_this_frame(resultbox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) sd = self.staticdata if sd.result_type == 'void': assert resultbox is None @@ -1337,30 +1326,25 @@ else: assert False - def finishframe_exception(self, exceptionbox, excvaluebox): - # detect and propagate some exceptions early: - # - AssertionError - # - all subclasses of JitException - if we_are_translated(): - from pypy.jit.metainterp.warmspot import JitException - e = self.cpu.ts.get_exception_obj(excvaluebox) - if isinstance(e, JitException) or isinstance(e, AssertionError): - raise Exception, e - # + def finishframe_exception(self): + excvaluebox = self.last_exc_value_box while self.framestack: frame = self.framestack[-1] - if frame.exception_target >= 0: - frame.pc = frame.exception_target - frame.exception_target = -1 - frame.exception_box = exceptionbox - frame.exc_value_box = excvaluebox - return True + code = frame.bytecode + position = frame.pc # <-- just after the insn that raised + if position < len(code): + opcode = ord(code[position]) + if opcode == self.staticdata.op_catch_exception: + # found a 'catch_exception' instruction; + # jump to the handler + target = ord(code[position+1]) | (ord(code[position+2])<<8) + frame.pc = target + raise ChangeFrame self.popframe() - if not self.is_blackholing(): - try: - self.compile_exit_frame_with_exception(excvaluebox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_exit_frame_with_exception(excvaluebox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base()) def check_recursion_invariant(self): @@ -1379,19 +1363,7 @@ else: print " ", print jitcode.name - raise Exception - - def raise_overflow_error(self): - etype, evalue = self.cpu.get_overflow_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) - - def raise_zero_division_error(self): - etype, evalue = self.cpu.get_zero_division_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) + raise AssertionError def create_empty_history(self): warmrunnerstate = self.staticdata.state @@ -1412,15 +1384,11 @@ @specialize.arg(1) def execute_and_record(self, opnum, descr, *argboxes): history.check_descr(descr) - assert (opnum != rop.CALL and opnum != rop.CALL_MAY_FORCE - and opnum != rop.OOSEND) + assert not (rop._CANRAISE_FIRST <= opnum <= rop._CANRAISE_LAST) # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - return resbox + resbox = executor.execute(self.cpu, self, opnum, descr, *argboxes) if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: return self._record_helper_pure(opnum, resbox, descr, *argboxes) else: @@ -1433,16 +1401,14 @@ # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute_varargs(self.cpu, opnum, argboxes, descr) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - else: - # check if the operation can be constant-folded away - argboxes = list(argboxes) - if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: - resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) - else: - resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) + resbox = executor.execute_varargs(self.cpu, self, + opnum, argboxes, descr) + # check if the operation can be constant-folded away + argboxes = list(argboxes) + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: + resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) + else: + resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) return resbox def _record_helper_pure(self, opnum, resbox, descr, *argboxes): @@ -1478,45 +1444,57 @@ op.pc = self.framestack[-1].pc op.name = self.framestack[-1].jitcode.name - def switch_to_blackhole(self, reason): + def execute_raised(self, exception, constant=False): + if isinstance(exception, JitException): + raise JitException, exception # go through + llexception = get_llexception(self.cpu, exception) + self.execute_ll_raised(llexception, constant) + + def execute_ll_raised(self, llexception, constant=False): + # Exception handling: when execute.do_call() gets an exception it + # calls metainterp.execute_raised(), which puts it into + # 'self.last_exc_value_box'. This is used shortly afterwards + # to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also + # to handle the following opcodes 'goto_if_exception_mismatch'. + llexception = self.cpu.ts.cast_to_ref(llexception) + exc_value_box = self.cpu.ts.get_exc_value_box(llexception) + if constant: + exc_value_box = exc_value_box.constbox() + self.last_exc_value_box = exc_value_box + self.class_of_last_exc_is_const = constant + # 'class_of_last_exc_is_const' means that the class of the value + # stored in the exc_value Box can be assumed to be a Const. This + # is only True after a GUARD_EXCEPTION or GUARD_CLASS. + + def clear_exception(self): + self.last_exc_value_box = None + + def aborted_tracing(self, reason): self.staticdata.profiler.count(reason) debug_print('~~~ ABORTING TRACING') - debug_stop('jit-tracing') - debug_start('jit-blackhole') - self.history = None # start blackholing self.staticdata.stats.aborted() - self.staticdata.profiler.end_tracing() - self.staticdata.profiler.start_blackhole() self.resumekey.reset_counter_from_failure() - switch_to_blackhole._dont_inline_ = True - def switch_to_blackhole_if_trace_too_long(self): - if not self.is_blackholing(): - warmrunnerstate = self.staticdata.state - if len(self.history.operations) > warmrunnerstate.trace_limit: - greenkey_of_huge_function = self.find_biggest_function() - self.portal_trace_positions = None - self.switch_to_blackhole(ABORT_TOO_LONG) - if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state - warmrunnerstate.disable_noninlinable_function( - greenkey_of_huge_function) + def blackhole_if_trace_too_long(self): + warmrunnerstate = self.staticdata.state + if len(self.history.operations) > warmrunnerstate.trace_limit: + greenkey_of_huge_function = self.find_biggest_function() + self.portal_trace_positions = None + if greenkey_of_huge_function is not None: + warmrunnerstate = self.staticdata.state + warmrunnerstate.disable_noninlinable_function( + greenkey_of_huge_function) + raise SwitchToBlackhole(ABORT_TOO_LONG) def _interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, - # a ContinueRunningNormally, or a GenerateMergePoint exception. + # a ExitFrameWithException, or a GenerateMergePoint exception. self.staticdata.stats.entered() - try: - while True: - self.framestack[-1].run_one_step() - self.switch_to_blackhole_if_trace_too_long() - if not we_are_translated(): - self.check_recursion_invariant() - finally: - if self.is_blackholing(): - self.staticdata.profiler.end_blackhole() - else: - self.staticdata.profiler.end_tracing() + while True: + self.framestack[-1].run_one_step() + self.blackhole_if_trace_too_long() + if not we_are_translated(): + self.check_recursion_invariant() def interpret(self): if we_are_translated(): @@ -1527,20 +1505,19 @@ except: import sys if sys.exc_info()[0] is not None: - codewriter.log.info(sys.exc_info()[0].__name__) + self.staticdata.log(sys.exc_info()[0].__name__) raise def compile_and_run_once(self, *args): debug_start('jit-tracing') self.staticdata._setup_once() + self.staticdata.profiler.start_tracing() self.create_empty_history() try: return self._compile_and_run_once(*args) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _compile_and_run_once(self, *args): original_boxes = self.initialize_state_from_start(*args) @@ -1553,20 +1530,22 @@ self.seen_can_enter_jit = False try: self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" def handle_guard_failure(self, key): + debug_start('jit-tracing') + self.staticdata.profiler.start_tracing() assert isinstance(key, compile.ResumeGuardDescr) self.initialize_state_from_guard_failure(key) try: return self._handle_guard_failure(key) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _handle_guard_failure(self, key): original_greenkey = key.original_greenkey @@ -1579,13 +1558,23 @@ try: self.prepare_resume_from_failure(key.guard_opnum) self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" + + def run_blackhole_interp_to_cancel_tracing(self, stb): + # We got a SwitchToBlackhole exception. Convert the framestack into + # a stack of blackhole interpreters filled with the same values, and + # run it. + from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl + self.aborted_tracing(stb.reason) + convert_and_run_from_pyjitpl(self, stb.raising_exception) + assert False # ^^^ must raise - def remove_consts_and_duplicates(self, boxes, startindex, endindex, - duplicates): - for i in range(startindex, endindex): + def remove_consts_and_duplicates(self, boxes, endindex, duplicates): + for i in range(endindex): box = boxes[i] if isinstance(box, Const) or box in duplicates: oldbox = box @@ -1595,22 +1584,19 @@ else: duplicates[box] = None - def reached_can_enter_jit(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + def reached_can_enter_jit(self, greenboxes, redboxes): duplicates = {} - self.remove_consts_and_duplicates(live_arg_boxes, - num_green_args, - len(live_arg_boxes), + self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) - live_arg_boxes = live_arg_boxes[:] + live_arg_boxes = greenboxes + redboxes if self.staticdata.virtualizable_info is not None: - # we use ':-1' to remove the last item, which is the virtualizable + # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, - 0, len(self.virtualizable_boxes)-1, duplicates) - live_arg_boxes += self.virtualizable_boxes[:-1] + live_arg_boxes += self.virtualizable_boxes + live_arg_boxes.pop() assert len(self.virtualref_boxes) == 0, "missing virtual_ref_finish()?" # Called whenever we reach the 'can_enter_jit' hint. # First, attempt to make a bridge: @@ -1639,11 +1625,12 @@ # Found! Compile it as a loop. if start < 0: # we cannot reconstruct the beginning of the proper loop - raise GiveUp + raise SwitchToBlackhole(ABORT_BRIDGE) # raises in case it works -- which is the common case self.compile(original_boxes, live_arg_boxes, start) # creation of the loop was cancelled! + self.staticdata.log('cancelled, going on...') # Otherwise, no loop found so far, so continue tracing. start = len(self.history.operations) @@ -1658,17 +1645,39 @@ return loop_token def prepare_resume_from_failure(self, opnum): + frame = self.framestack[-1] if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now - self.framestack[-1].follow_jump() + frame.pc = frame.jitcode.follow_jump(frame.pc) elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping - self.framestack[-1].dont_follow_jump() - elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION - or opnum == rop.GUARD_NOT_FORCED): - self.handle_exception() + pass + elif opnum == rop.GUARD_VALUE or opnum == rop.GUARD_CLASS: + pass # the pc is already set to the *start* of the opcode + elif (opnum == rop.GUARD_NONNULL or + opnum == rop.GUARD_ISNULL or + opnum == rop.GUARD_NONNULL_CLASS): + pass # the pc is already set to the *start* of the opcode + elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION: + exception = self.cpu.grab_exc_value() + if exception: + self.execute_ll_raised(lltype.cast_opaque_ptr(rclass.OBJECTPTR, + exception)) + else: + self.clear_exception() + try: + self.handle_possible_exception() + except ChangeFrame: + pass elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected - self.raise_overflow_error() - elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL: - self.framestack[-1].ignore_next_guard_nullness(opnum) + self.execute_raised(OverflowError(), constant=True) + try: + self.finishframe_exception() + except ChangeFrame: + pass + elif opnum == rop.GUARD_OVERFLOW: # no longer overflowing + self.clear_exception() + else: + from pypy.jit.metainterp.resoperation import opname + raise NotImplementedError(opname[opnum]) def compile(self, original_boxes, live_arg_boxes, start): num_green_args = self.staticdata.num_green_args @@ -1753,15 +1762,13 @@ def initialize_state_from_start(self, *args): self.in_recursion = -1 # always one portal around - self.staticdata.profiler.start_tracing() num_green_args = self.staticdata.num_green_args original_boxes = [] self._initialize_from_start(original_boxes, num_green_args, *args) # ----- make a new frame ----- self.framestack = [] f = self.newframe(self.staticdata.portal_code) - f.pc = 0 - f.env = original_boxes[:] + f.setup_call(original_boxes) self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) return original_boxes @@ -1769,20 +1776,9 @@ def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack self.in_recursion = -1 # always one portal around - inputargs_and_holes = self.cpu.make_boxes_from_latest_values( - resumedescr) - must_compile = resumedescr.must_compile(self.staticdata, - inputargs_and_holes) - if must_compile: - debug_start('jit-tracing') - self.history = history.History() - self.history.inputargs = [box for box in inputargs_and_holes if box] - self.staticdata.profiler.start_tracing() - else: - debug_start('jit-blackhole') - self.staticdata.profiler.start_blackhole() - self.history = None # this means that is_blackholing() is true - self.rebuild_state_after_failure(resumedescr, inputargs_and_holes) + self.history = history.History() + inputargs_and_holes = self.rebuild_state_after_failure(resumedescr) + self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): vinfo = self.staticdata.virtualizable_info @@ -1804,9 +1800,6 @@ vinfo.clear_vable_token(virtualizable) def vable_and_vrefs_before_residual_call(self): - if self.is_blackholing(): - return - # vrefinfo = self.staticdata.virtualref_info for i in range(1, len(self.virtualref_boxes), 2): vrefbox = self.virtualref_boxes[i] @@ -1827,37 +1820,31 @@ force_token_box], None, descr=vinfo.vable_token_descr) - def vable_and_vrefs_after_residual_call(self): - if self.is_blackholing(): - escapes = True - else: - escapes = False - # - vrefinfo = self.staticdata.virtualref_info - for i in range(0, len(self.virtualref_boxes), 2): - virtualbox = self.virtualref_boxes[i] - vrefbox = self.virtualref_boxes[i+1] - vref = vrefbox.getref_base() - if vrefinfo.tracing_after_residual_call(vref): - # this vref was really a virtual_ref, but it escaped - # during this CALL_MAY_FORCE. Mark this fact by - # generating a VIRTUAL_REF_FINISH on it and replacing - # it by ConstPtr(NULL). - self.stop_tracking_virtualref(i) - # - vinfo = self.staticdata.virtualizable_info - if vinfo is not None: - virtualizable_box = self.virtualizable_boxes[-1] - virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) - if vinfo.tracing_after_residual_call(virtualizable): - # the virtualizable escaped during CALL_MAY_FORCE. - escapes = True - # - if escapes: - self.switch_to_blackhole(ABORT_ESCAPE) - # - if escapes: - self.load_fields_from_virtualizable() + def vrefs_after_residual_call(self): + vrefinfo = self.staticdata.virtualref_info + for i in range(0, len(self.virtualref_boxes), 2): + virtualbox = self.virtualref_boxes[i] + vrefbox = self.virtualref_boxes[i+1] + vref = vrefbox.getref_base() + if vrefinfo.tracing_after_residual_call(vref): + # this vref was really a virtual_ref, but it escaped + # during this CALL_MAY_FORCE. Mark this fact by + # generating a VIRTUAL_REF_FINISH on it and replacing + # it by ConstPtr(NULL). + self.stop_tracking_virtualref(i) + + def vable_after_residual_call(self): + vinfo = self.staticdata.virtualizable_info + if vinfo is not None: + virtualizable_box = self.virtualizable_boxes[-1] + virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + if vinfo.tracing_after_residual_call(virtualizable): + # the virtualizable escaped during CALL_MAY_FORCE. + self.load_fields_from_virtualizable() + raise SwitchToBlackhole(ABORT_ESCAPE, raising_exception=True) + # ^^^ we set 'raising_exception' to True because we must still + # have the eventual exception raised (this is normally done + # after the call to vable_after_residual_call()). def stop_tracking_virtualref(self, i): virtualbox = self.virtualref_boxes[i] @@ -1871,44 +1858,37 @@ # mark by replacing it with ConstPtr(NULL) self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL - def handle_exception(self): - etype = self.cpu.get_exception() - evalue = self.cpu.get_exc_value() - assert bool(etype) == bool(evalue) - self.cpu.clear_exception() + def handle_possible_exception(self): frame = self.framestack[-1] - if etype: - exception_box = self.cpu.ts.get_exception_box(etype) - exc_value_box = self.cpu.ts.get_exc_value_box(evalue) - op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION, + if self.last_exc_value_box is not None: + exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box) + op = frame.generate_guard(rop.GUARD_EXCEPTION, None, [exception_box]) - if op: - op.result = exc_value_box - return self.finishframe_exception(exception_box, exc_value_box) + assert op is not None + op.result = self.last_exc_value_box + self.class_of_last_exc_is_const = True + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) - return False - - def assert_no_exception(self): - assert not self.cpu.get_exception() - return False + frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) - def handle_overflow_error(self): + def handle_possible_overflow_error(self): frame = self.framestack[-1] - if self.cpu._overflow_flag: - self.cpu._overflow_flag = False - frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None, []) - return self.raise_overflow_error() + if self.last_exc_value_box is not None: + frame.generate_guard(rop.GUARD_OVERFLOW, None) + assert isinstance(self.last_exc_value_box, Const) + assert self.class_of_last_exc_is_const + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None, []) - return False + frame.generate_guard(rop.GUARD_NO_OVERFLOW, None) + + def assert_no_exception(self): + assert self.last_exc_value_box is None - def rebuild_state_after_failure(self, resumedescr, newboxes): + def rebuild_state_after_failure(self, resumedescr): vinfo = self.staticdata.virtualizable_info self.framestack = [] - expect_virtualizable = vinfo is not None - virtualizable_boxes, virtualref_boxes = resume.rebuild_from_resumedata( - self, newboxes, resumedescr, expect_virtualizable) + boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) + inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists # # virtual refs: make the vrefs point to the freshly allocated virtuals self.virtualref_boxes = virtualref_boxes @@ -1921,7 +1901,7 @@ # # virtualizable: synchronize the real virtualizable and the local # boxes, in whichever direction is appropriate - if expect_virtualizable: + if vinfo is not None: self.virtualizable_boxes = virtualizable_boxes # just jumped away from assembler (case 4 in the comment in # virtualizable.py) into tracing (case 2); check that vable_token @@ -1930,13 +1910,14 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if self._already_allocated_resume_virtuals is not None: + if 0: ## self._already_allocated_resume_virtuals is not None: # resuming from a ResumeGuardForcedDescr: load the new values # currently stored on the virtualizable fields self.load_fields_from_virtualizable() else: # normal case: fill the virtualizable with the local boxes self.synchronize_virtualizable() + return inputargs_and_holes def check_synchronized_virtualizable(self): if not we_are_translated(): @@ -1953,8 +1934,8 @@ def load_fields_from_virtualizable(self): # Force a reload of the virtualizable fields into the local - # boxes (called only in escaping cases) - assert self.is_blackholing() + # boxes (called only in escaping cases). Only call this function + # just before SwitchToBlackhole. vinfo = self.staticdata.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] @@ -2003,11 +1984,9 @@ return boxes def replace_box(self, oldbox, newbox): + assert isinstance(oldbox, Box) for frame in self.framestack: - boxes = frame.env - for i in range(len(boxes)): - if boxes[i] is oldbox: - boxes[i] = newbox + frame.replace_active_box_in_frame(oldbox, newbox) boxes = self.virtualref_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2019,8 +1998,6 @@ boxes[i] = newbox def find_biggest_function(self): - assert not self.is_blackholing() - start_stack = [] max_size = 0 max_key = None @@ -2042,23 +2019,158 @@ max_key = key return max_key - def direct_assembler_call(self, pc, varargs, token, call_position): - """ Generate a direct call to assembler for portal entry point. + def direct_assembler_call(self, token): + """ Generate a direct call to assembler for portal entry point, + patching the CALL_MAY_FORCE that occurred just now. """ - assert not self.is_blackholing() # XXX + op = self.history.operations.pop() + assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args - args = varargs[num_green_args + 1:] - resbox = self.history.operations[call_position].result - rest = self.history.slice_history_at(call_position) + args = op.args[num_green_args + 1:] if self.staticdata.virtualizable_info is not None: vindex = self.staticdata.virtualizable_info.index_of_virtualizable vbox = args[vindex - num_green_args] - args += self.gen_load_from_other_virtualizable(vbox) - self.history.record(rop.CALL_ASSEMBLER, args[:], resbox, descr=token) - self.history.operations += rest + args = args + self.gen_load_from_other_virtualizable(vbox) + # ^^^ and not "+=", which makes 'args' a resizable list + op.opnum = rop.CALL_ASSEMBLER + op.args = args + op.descr = token + self.history.operations.append(op) -class GenerateMergePoint(Exception): +# ____________________________________________________________ + +class GenerateMergePoint(JitException): def __init__(self, args, target_loop_token): assert target_loop_token is not None self.argboxes = args self.target_loop_token = target_loop_token + +class ChangeFrame(JitException): + """Raised after we mutated metainterp.framestack, in order to force + it to reload the current top-of-stack frame that gets interpreted.""" + +class SwitchToBlackhole(JitException): + def __init__(self, reason, raising_exception=False): + self.reason = reason + self.raising_exception = raising_exception + # ^^^ must be set to True if the SwitchToBlackhole is raised at a + # point where the exception on metainterp.last_exc_value_box + # is supposed to be raised. The default False means that it + # should just be copied into the blackhole interp, but not raised. + +# ____________________________________________________________ + +def _get_opimpl_method(name, argcodes): + from pypy.jit.metainterp.blackhole import signedord + # + def handler(self, position): + assert position >= 0 + args = () + next_argcode = 0 + code = self.bytecode + orgpc = position + position += 1 + for argtype in argtypes: + if argtype == "box": # a box, of whatever type + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = self.registers_i[ord(code[position])] + elif argcode == 'c': + value = ConstInt(signedord(code[position])) + elif argcode == 'r': + value = self.registers_r[ord(code[position])] + elif argcode == 'f': + value = self.registers_f[ord(code[position])] + else: + raise AssertionError("bad argcode") + position += 1 + elif argtype == "descr" or argtype == "jitcode": + assert argcodes[next_argcode] == 'd' + next_argcode = next_argcode + 1 + index = ord(code[position]) | (ord(code[position+1])<<8) + value = self.metainterp.staticdata.opcode_descrs[index] + if argtype == "jitcode": + assert isinstance(value, JitCode) + position += 2 + elif argtype == "label": + assert argcodes[next_argcode] == 'L' + next_argcode = next_argcode + 1 + value = ord(code[position]) | (ord(code[position+1])<<8) + position += 2 + elif argtype == "boxes": # a list of boxes of some type + length = ord(code[position]) + value = [None] * length + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + next_argcode = next_argcode + 1 + position += 1 + length + elif argtype == "boxes2": # two lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + value = [None] * (length1 + length2) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + next_argcode = next_argcode + 2 + position = position2 + 1 + length2 + elif argtype == "boxes3": # three lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + position3 = position2 + 1 + length2 + length3 = ord(code[position3]) + value = [None] * (length1 + length2 + length3) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + self.prepare_list_of_boxes(value, length1 + length2, position3, + argcodes[next_argcode + 2]) + next_argcode = next_argcode + 3 + position = position3 + 1 + length3 + elif argtype == "orgpc": + value = orgpc + else: + raise AssertionError("bad argtype: %r" % (argtype,)) + args += (value,) + # + num_return_args = len(argcodes) - next_argcode + assert num_return_args == 0 or num_return_args == 2 + if num_return_args: + # Save the type of the resulting box. This is needed if there is + # a get_list_of_active_boxes(). See comments there. + self._result_argcode = argcodes[next_argcode + 1] + position += 1 + else: + self._result_argcode = 'v' + self.pc = position + # + if not we_are_translated(): + print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))), + try: + resultbox = unboundmethod(self, *args) + except Exception, e: + print '-> %s!' % e.__class__.__name__ + raise + if num_return_args == 0: + print + assert resultbox is None + else: + print '-> %r' % (resultbox,) + assert argcodes[next_argcode] == '>' + result_argcode = argcodes[next_argcode + 1] + assert resultbox.type == {'i': history.INT, + 'r': history.REF, + 'f': history.FLOAT}[result_argcode] + else: + resultbox = unboundmethod(self, *args) + # + self.make_result_of_lastop(resultbox) + # + unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func + argtypes = unrolling_iterable(unboundmethod.argtypes) + handler.func_name = 'handler_' + name + return handler Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resoperation.py Tue Jun 8 19:48:40 2010 @@ -22,10 +22,11 @@ self.setdescr(descr) def setdescr(self, descr): - # for 'call', 'new', 'getfield_gc'...: the descr is a number provided - # by the backend holding details about the type of the operation -- - # actually an instance of a class, typically Descr, that inherits - # from AbstractDescr + # for 'call', 'new', 'getfield_gc'...: the descr is a prebuilt + # instance provided by the backend holding details about the type + # of the operation. It must inherit from AbstractDescr. The + # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(), + # cpu.calldescrof(), and cpu.typedescrof(). from pypy.jit.metainterp.history import check_descr check_descr(descr) self.descr = descr @@ -134,10 +135,9 @@ '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations ----- '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations ----- - 'OOSEND_PURE', # ootype operation + #'OOSEND_PURE', # ootype operation 'CALL_PURE', # - 'CAST_PTR_TO_INT/1', 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', @@ -156,7 +156,6 @@ 'FLOAT_TRUEDIV/2', 'FLOAT_NEG/1', 'FLOAT_ABS/1', - 'FLOAT_IS_TRUE/1b', 'CAST_FLOAT_TO_INT/1', 'CAST_INT_TO_FLOAT/1', # @@ -177,15 +176,15 @@ 'FLOAT_GT/2b', 'FLOAT_GE/2b', # + 'INT_IS_ZERO/1b', 'INT_IS_TRUE/1b', 'INT_NEG/1', 'INT_INVERT/1', - 'BOOL_NOT/1b', # 'SAME_AS/1', # gets a Const or a Box, turns it into another Box # - 'OOIS/2b', - 'OOISNOT/2b', + 'PTR_EQ/2b', + 'PTR_NE/2b', # 'ARRAYLEN_GC/1d', 'STRLEN/1', @@ -197,8 +196,8 @@ 'UNICODEGETITEM/2', # # ootype operations - 'INSTANCEOF/1db', - 'SUBCLASSOF/2b', + #'INSTANCEOF/1db', + #'SUBCLASSOF/2b', # '_ALWAYS_PURE_LAST', # ----- end of always_pure operations ----- @@ -209,29 +208,29 @@ 'NEW_WITH_VTABLE/1', 'NEW_ARRAY/1d', 'FORCE_TOKEN/0', - 'VIRTUAL_REF/2', + 'VIRTUAL_REF/2', # removed before it's passed to the backend '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations ----- 'SETARRAYITEM_GC/3d', 'SETARRAYITEM_RAW/3d',#only added by backend.llsupport.gc.rewrite_assembler 'SETFIELD_GC/2d', 'SETFIELD_RAW/2d', - 'ARRAYCOPY/7d', + 'ARRAYCOPY/7d', # removed before it's passed to the backend 'NEWSTR/1', 'STRSETITEM/3', 'UNICODESETITEM/3', 'NEWUNICODE/1', - 'RUNTIMENEW/1', # ootype operation + #'RUNTIMENEW/1', # ootype operation 'COND_CALL_GC_WB', # [objptr, newvalue] (for the write barrier) 'DEBUG_MERGE_POINT/1', # debugging only - 'VIRTUAL_REF_FINISH/2', + 'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend '_CANRAISE_FIRST', # ----- start of can_raise operations ----- 'CALL', 'CALL_ASSEMBLER', 'CALL_MAY_FORCE', 'CALL_LOOPINVARIANT', - 'OOSEND', # ootype operation + #'OOSEND', # ootype operation '_CANRAISE_LAST', # ----- end of can_raise operations ----- '_OVF_FIRST', # ----- start of is_ovf operations ----- Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/resume.py Tue Jun 8 19:48:40 2010 @@ -1,10 +1,12 @@ import sys, os -from pypy.jit.metainterp.history import Box, Const, ConstInt, INT, REF +from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat +from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import jitprof -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rlib import rarithmetic -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print @@ -21,26 +23,29 @@ self.boxes = boxes class FrameInfo(object): - __slots__ = ('prev', 'jitcode', 'pc', 'exception_target') + __slots__ = ('prev', 'jitcode', 'pc') - def __init__(self, prev, frame): + def __init__(self, prev, jitcode, pc): self.prev = prev - self.jitcode = frame.jitcode - self.pc = frame.pc - self.exception_target = frame.exception_target + self.jitcode = jitcode + self.pc = pc def _ensure_parent_resumedata(framestack, n): target = framestack[n] - if n == 0 or target.parent_resumedata_frame_info_list is not None: + if n == 0: return - _ensure_parent_resumedata(framestack, n-1) back = framestack[n-1] + if target.parent_resumedata_frame_info_list is not None: + assert target.parent_resumedata_frame_info_list.pc == back.pc + return + _ensure_parent_resumedata(framestack, n-1) target.parent_resumedata_frame_info_list = FrameInfo( back.parent_resumedata_frame_info_list, - back) + back.jitcode, + back.pc) target.parent_resumedata_snapshot = Snapshot( back.parent_resumedata_snapshot, - back.env[:]) + back.get_list_of_active_boxes(True)) def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, storage): @@ -48,12 +53,15 @@ top = framestack[n] _ensure_parent_resumedata(framestack, n) frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, - top) + top.jitcode, top.pc) storage.rd_frame_info_list = frame_info_list - snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:]) - snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now + snapshot = Snapshot(top.parent_resumedata_snapshot, + top.get_list_of_active_boxes(False)) if virtualizable_boxes is not None: - snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now + boxes = virtualref_boxes + virtualizable_boxes + else: + boxes = virtualref_boxes[:] + snapshot = Snapshot(snapshot, boxes) storage.rd_snapshot = snapshot class Numbering(object): @@ -182,6 +190,7 @@ n += 1 liveboxes[box] = tagged nums[i] = tagged + # numb = Numbering(numb1, nums) self.numberings[snapshot] = numb, liveboxes, v return numb, liveboxes.copy(), v @@ -388,10 +397,10 @@ class AbstractVirtualInfo(object): - def allocate(self, metainterp): - raise NotImplementedError - def setfields(self, metainterp, box, fn_decode_box): - raise NotImplementedError + #def allocate(self, metainterp): + # raise NotImplementedError + #def setfields(self, decoder, struct): + # raise NotImplementedError def equals(self, fieldnums): return tagged_list_eq(self.fieldnums, fieldnums) def set_content(self, fieldnums): @@ -405,12 +414,11 @@ self.fielddescrs = fielddescrs #self.fieldnums = ... - def setfields(self, metainterp, box, fn_decode_box): + @specialize.argtype(1) + def setfields(self, decoder, struct): for i in range(len(self.fielddescrs)): - fieldbox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETFIELD_GC, - self.fielddescrs[i], - box, fieldbox) + descr = self.fielddescrs[i] + decoder.setfield(descr, struct, self.fieldnums[i]) def debug_prints(self): assert len(self.fielddescrs) == len(self.fieldnums) @@ -424,9 +432,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.known_class = known_class - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - None, self.known_class) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_with_vtable(self.known_class) def debug_prints(self): debug_print("\tvirtualinfo", self.known_class.repr_rpython()) @@ -437,8 +445,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.typedescr = typedescr - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW, self.typedescr) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_struct(self.typedescr) def debug_prints(self): debug_print("\tvstructinfo", self.typedescr.repr_rpython()) @@ -449,117 +458,457 @@ self.arraydescr = arraydescr #self.fieldnums = ... - def allocate(self, metainterp): + @specialize.argtype(1) + def allocate(self, decoder): length = len(self.fieldnums) - return metainterp.execute_and_record(rop.NEW_ARRAY, - self.arraydescr, - ConstInt(length)) - - def setfields(self, metainterp, box, fn_decode_box): - for i in range(len(self.fieldnums)): - itembox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETARRAYITEM_GC, - self.arraydescr, - box, ConstInt(i), itembox) + return decoder.allocate_array(self.arraydescr, length) + + @specialize.argtype(1) + def setfields(self, decoder, array): + arraydescr = self.arraydescr + length = len(self.fieldnums) + # NB. the check for the kind of array elements is moved out of the loop + if arraydescr.is_array_of_pointers(): + for i in range(length): + decoder.setarrayitem_ref(arraydescr, array, i, + self.fieldnums[i]) + elif arraydescr.is_array_of_floats(): + for i in range(length): + decoder.setarrayitem_float(arraydescr, array, i, + self.fieldnums[i]) + else: + for i in range(length): + decoder.setarrayitem_int(arraydescr, array, i, + self.fieldnums[i]) def debug_prints(self): debug_print("\tvarrayinfo", self.arraydescr) for i in self.fieldnums: debug_print("\t\t", str(untag(i))) +# ____________________________________________________________ -def rebuild_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - frameinfo = storage.rd_frame_info_list - while True: - env = resumereader.consume_boxes() - f = metainterp.newframe(frameinfo.jitcode) - f.setup_resume_at_op(frameinfo.pc, frameinfo.exception_target, env) - frameinfo = frameinfo.prev - if frameinfo is None: - break - metainterp.framestack.reverse() - return virtualizable_boxes, virtualref_boxes - -def force_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - return virtualizable_boxes, virtualref_boxes, resumereader.virtuals - - -class ResumeDataReader(object): +class AbstractResumeDataReader(object): + """A base mixin containing the logic to reconstruct virtuals out of + guard failure. There are two implementations of this mixin: + ResumeDataBoxReader for when we are compiling (i.e. when we have a + metainterp), and ResumeDataDirectReader for when we are merely + blackholing and want the best performance. + """ + _mixin_ = True virtuals = None + virtual_default = None - def __init__(self, storage, liveboxes, metainterp=None): + def _init(self, cpu, storage): + self.cpu = cpu self.cur_numb = storage.rd_numb self.consts = storage.rd_consts - self.liveboxes = liveboxes - self.cpu = metainterp.cpu - self._prepare_virtuals(metainterp, storage.rd_virtuals) - self._prepare_pendingfields(metainterp, storage.rd_pendingfields) - def _prepare_virtuals(self, metainterp, virtuals): + def _prepare(self, storage): + self._prepare_virtuals(storage.rd_virtuals) + self._prepare_pendingfields(storage.rd_pendingfields) + + def _prepare_virtuals(self, virtuals): if virtuals: - v = metainterp._already_allocated_resume_virtuals - if v is not None: - self.virtuals = v - return - self.virtuals = [None] * len(virtuals) + self.virtuals = [self.virtual_default] * len(virtuals) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - self.virtuals[i] = vinfo.allocate(metainterp) + self.virtuals[i] = vinfo.allocate(self) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - vinfo.setfields(metainterp, self.virtuals[i], - self._decode_box) + vinfo.setfields(self, self.virtuals[i]) - def _prepare_pendingfields(self, metainterp, pendingfields): - if pendingfields: - if metainterp._already_allocated_resume_virtuals is not None: - return + def _prepare_pendingfields(self, pendingfields): + if pendingfields is not None: for descr, num, fieldnum in pendingfields: - box = self._decode_box(num) - fieldbox = self._decode_box(fieldnum) - metainterp.execute_and_record(rop.SETFIELD_GC, - descr, box, fieldbox) - - def consume_boxes(self): - numb = self.cur_numb - assert numb is not None - nums = numb.nums - n = len(nums) - boxes = [None] * n - for i in range(n): - boxes[i] = self._decode_box(nums[i]) - self.cur_numb = numb.prev - return boxes + struct = self.decode_ref(num) + self.setfield(descr, struct, fieldnum) + + def _prepare_next_section(self, info): + # Use info.enumerate_vars(), normally dispatching to + # pypy.jit.codewriter.jitcode. Some tests give a different 'info'. + info.enumerate_vars(self._callback_i, + self._callback_r, + self._callback_f, + self.unique_id) # <-- annotation hack + self.cur_numb = self.cur_numb.prev + + def _callback_i(self, index, register_index): + value = self.decode_int(self.cur_numb.nums[index]) + self.write_an_int(register_index, value) + + def _callback_r(self, index, register_index): + value = self.decode_ref(self.cur_numb.nums[index]) + self.write_a_ref(register_index, value) + + def _callback_f(self, index, register_index): + value = self.decode_float(self.cur_numb.nums[index]) + self.write_a_float(register_index, value) + + def done(self): + self.cpu.clear_latest_values(self.cpu.get_latest_value_count()) + +# ---------- when resuming for pyjitpl.py, make boxes ---------- + +def rebuild_from_resumedata(metainterp, storage, virtualizable_info): + resumereader = ResumeDataBoxReader(storage, metainterp) + boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info) + virtualizable_boxes, virtualref_boxes = boxes + frameinfo = storage.rd_frame_info_list + while True: + f = metainterp.newframe(frameinfo.jitcode) + f.setup_resume_at_op(frameinfo.pc) + resumereader.consume_boxes(f.get_current_position_info(), + f.registers_i, f.registers_r, f.registers_f) + frameinfo = frameinfo.prev + if frameinfo is None: + break + metainterp.framestack.reverse() + resumereader.done() + return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes + +class ResumeDataBoxReader(AbstractResumeDataReader): + unique_id = lambda: None - def _decode_box(self, tagged): + def __init__(self, storage, metainterp): + self._init(metainterp.cpu, storage) + self.metainterp = metainterp + self.liveboxes = [None] * metainterp.cpu.get_latest_value_count() + self._prepare(storage) + + def consume_boxes(self, info, boxes_i, boxes_r, boxes_f): + self.boxes_i = boxes_i + self.boxes_r = boxes_r + self.boxes_f = boxes_f + self._prepare_next_section(info) + + def consume_virtualizable_boxes(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], and use it to know how many + # boxes of which type we have to return. This does not write + # anything into the virtualizable. + virtualizablebox = self.decode_ref(nums[-1]) + virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox) + return vinfo.load_list_of_boxes(virtualizable, self, nums) + + def consume_virtualref_boxes(self, nums, end): + # Returns a list of boxes, assumed to be all BoxPtrs. + # We leave up to the caller to call vrefinfo.continue_tracing(). + assert (end & 1) == 0 + return [self.decode_ref(nums[i]) for i in range(end)] + + def consume_vref_and_vable_boxes(self, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if vinfo is None: + virtualizable_boxes = None + end = len(nums) + else: + virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums) + end = len(nums) - len(virtualizable_boxes) + virtualref_boxes = self.consume_virtualref_boxes(nums, end) + return virtualizable_boxes, virtualref_boxes + + def allocate_with_vtable(self, known_class): + return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE, + None, known_class) + + def allocate_struct(self, typedescr): + return self.metainterp.execute_and_record(rop.NEW, typedescr) + + def allocate_array(self, arraydescr, length): + return self.metainterp.execute_and_record(rop.NEW_ARRAY, + arraydescr, ConstInt(length)) + + def setfield(self, descr, structbox, fieldnum): + if descr.is_pointer_field(): + kind = REF + elif descr.is_float_field(): + kind = FLOAT + else: + kind = INT + fieldbox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETFIELD_GC, descr, + structbox, fieldbox) + + def setarrayitem_int(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, INT) + + def setarrayitem_ref(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, REF) + + def setarrayitem_float(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, FLOAT) + + def setarrayitem(self, arraydescr, arraybox, index, fieldnum, kind): + itembox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETARRAYITEM_GC, + arraydescr, arraybox, + ConstInt(index), itembox) + + def decode_int(self, tagged): + return self.decode_box(tagged, INT) + def decode_ref(self, tagged): + return self.decode_box(tagged, REF) + def decode_float(self, tagged): + return self.decode_box(tagged, FLOAT) + + def decode_box(self, tagged, kind): num, tag = untag(tagged) if tag == TAGCONST: if tagged_eq(tagged, NULLREF): - return self.cpu.ts.CONST_NULL - return self.consts[num] + box = self.cpu.ts.CONST_NULL + else: + box = self.consts[num] elif tag == TAGVIRTUAL: virtuals = self.virtuals assert virtuals is not None - return virtuals[num] + box = virtuals[num] + elif tag == TAGINT: + box = ConstInt(num) + else: + assert tag == TAGBOX + box = self.liveboxes[num] + if box is None: + box = self.load_box_from_cpu(num, kind) + assert box.type == kind + return box + + def load_box_from_cpu(self, num, kind): + if num < 0: + num += len(self.liveboxes) + assert num >= 0 + if kind == INT: + box = BoxInt(self.cpu.get_latest_value_int(num)) + elif kind == REF: + box = BoxPtr(self.cpu.get_latest_value_ref(num)) + elif kind == FLOAT: + box = BoxFloat(self.cpu.get_latest_value_float(num)) + else: + assert 0, "bad kind: %d" % ord(kind) + self.liveboxes[num] = box + return box + + def decode_box_of_type(self, TYPE, tagged): + kind = getkind(TYPE) + if kind == 'int': kind = INT + elif kind == 'ref': kind = REF + elif kind == 'float': kind = FLOAT + else: raise AssertionError(kind) + return self.decode_box(tagged, kind) + decode_box_of_type._annspecialcase_ = 'specialize:arg(1)' + + def write_an_int(self, index, box): + self.boxes_i[index] = box + def write_a_ref(self, index, box): + self.boxes_r[index] = box + def write_a_float(self, index, box): + self.boxes_f[index] = box + +# ---------- when resuming for blackholing, get direct values ---------- + +def blackhole_from_resumedata(blackholeinterpbuilder, storage, + all_virtuals=None): + resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, + all_virtuals) + vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + # + # First get a chain of blackhole interpreters whose length is given + # by the depth of rd_frame_info_list. The first one we get must be + # the bottom one, i.e. the last one in the chain, in order to make + # the comment in BlackholeInterpreter.setposition() valid. + nextbh = None + frameinfo = storage.rd_frame_info_list + while True: + curbh = blackholeinterpbuilder.acquire_interp() + curbh.nextblackholeinterp = nextbh + nextbh = curbh + frameinfo = frameinfo.prev + if frameinfo is None: + break + firstbh = nextbh + # + # Now fill the blackhole interpreters with resume data. + curbh = firstbh + frameinfo = storage.rd_frame_info_list + while True: + curbh.setposition(frameinfo.jitcode, frameinfo.pc) + resumereader.consume_one_section(curbh) + curbh = curbh.nextblackholeinterp + frameinfo = frameinfo.prev + if frameinfo is None: + break + resumereader.done() + return firstbh + +def force_from_resumedata(metainterp_sd, storage): + resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) + resumereader.handling_async_forcing() + vinfo = metainterp_sd.virtualizable_info + vrefinfo = metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + return resumereader.virtuals + +class ResumeDataDirectReader(AbstractResumeDataReader): + unique_id = lambda: None + virtual_default = lltype.nullptr(llmemory.GCREF.TO) + resume_after_guard_not_forced = 0 + # 0: not a GUARD_NOT_FORCED + # 1: in handle_async_forcing + # 2: resuming from the GUARD_NOT_FORCED + + def __init__(self, cpu, storage, all_virtuals=None): + self._init(cpu, storage) + if all_virtuals is None: # common case + self._prepare(storage) + else: + # special case for resuming after a GUARD_NOT_FORCED: we already + # have the virtuals + self.resume_after_guard_not_forced = 2 + self.virtuals = all_virtuals + + def handling_async_forcing(self): + self.resume_after_guard_not_forced = 1 + + def consume_one_section(self, blackholeinterp): + self.blackholeinterp = blackholeinterp + info = blackholeinterp.get_current_position_info() + self._prepare_next_section(info) + + def consume_virtualref_info(self, vrefinfo, nums, end): + # we have to decode a list of references containing pairs + # [..., virtual, vref, ...] stopping at 'end' + assert (end & 1) == 0 + for i in range(0, end, 2): + virtual = self.decode_ref(nums[i]) + vref = self.decode_ref(nums[i+1]) + # For each pair, we store the virtual inside the vref. + vrefinfo.continue_tracing(vref, virtual) + + def consume_vable_info(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], load all other values + # from the CPU stack, and copy them into the virtualizable + if vinfo is None: + return len(nums) + virtualizable = self.decode_ref(nums[-1]) + virtualizable = vinfo.cast_gcref_to_vtype(virtualizable) + if self.resume_after_guard_not_forced == 1: + # in the middle of handle_async_forcing() + assert virtualizable.vable_token + virtualizable.vable_token = vinfo.TOKEN_NONE + else: + # just jumped away from assembler (case 4 in the comment in + # virtualizable.py) into tracing (case 2); check that vable_token + # is and stays 0. Note the call to reset_vable_token() in + # warmstate.py. + assert not virtualizable.vable_token + return vinfo.write_from_resume_data_partial(virtualizable, self, nums) + + def load_value_of_type(self, TYPE, tagged): + from pypy.jit.metainterp.warmstate import specialize_value + kind = getkind(TYPE) + if kind == 'int': + x = self.decode_int(tagged) + elif kind == 'ref': + x = self.decode_ref(tagged) + elif kind == 'float': + x = self.decode_float(tagged) + else: + raise AssertionError(kind) + return specialize_value(TYPE, x) + load_value_of_type._annspecialcase_ = 'specialize:arg(1)' + + def consume_vref_and_vable(self, vrefinfo, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if self.resume_after_guard_not_forced != 2: + end_vref = self.consume_vable_info(vinfo, nums) + self.consume_virtualref_info(vrefinfo, nums, end_vref) + + def allocate_with_vtable(self, known_class): + from pypy.jit.metainterp.executor import exec_new_with_vtable + return exec_new_with_vtable(self.cpu, known_class) + + def allocate_struct(self, typedescr): + return self.cpu.bh_new(typedescr) + + def allocate_array(self, arraydescr, length): + return self.cpu.bh_new_array(arraydescr, length) + + def setfield(self, descr, struct, fieldnum): + if descr.is_pointer_field(): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setfield_gc_r(struct, descr, newvalue) + elif descr.is_float_field(): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setfield_gc_f(struct, descr, newvalue) + else: + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setfield_gc_i(struct, descr, newvalue) + + def setarrayitem_int(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setarrayitem_gc_i(arraydescr, array, index, newvalue) + + def setarrayitem_ref(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setarrayitem_gc_r(arraydescr, array, index, newvalue) + + def setarrayitem_float(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setarrayitem_gc_f(arraydescr, array, index, newvalue) + + def decode_int(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getint() elif tag == TAGINT: - return ConstInt(num) + return num else: assert tag == TAGBOX - return self.liveboxes[num] + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_int(num) + + def decode_ref(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + if tagged_eq(tagged, NULLREF): + return self.cpu.ts.NULLREF + return self.consts[num].getref_base() + elif tag == TAGVIRTUAL: + virtuals = self.virtuals + assert virtuals is not None + return virtuals[num] + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_ref(num) + + def decode_float(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getfloat() + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_float(num) + + def write_an_int(self, index, int): + self.blackholeinterp.setarg_i(index, int) + + def write_a_ref(self, index, ref): + self.blackholeinterp.setarg_r(index, ref) + + def write_a_float(self, index, float): + self.blackholeinterp.setarg_f(index, float) # ____________________________________________________________ @@ -576,7 +925,7 @@ except AttributeError: jitcodename = str(compute_unique_id(frameinfo.jitcode)) debug_print('\tjitcode/pc', jitcodename, - frameinfo.pc, frameinfo.exception_target, + frameinfo.pc, 'at', compute_unique_id(frameinfo)) frameinfo = frameinfo.prev numb = storage.rd_numb Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/simple_optimize.py Tue Jun 8 19:48:40 2010 @@ -10,12 +10,16 @@ def transform(op): from pypy.jit.metainterp.history import AbstractDescr # change ARRAYCOPY to call, so we don't have to pass around - # unnecessary information to the backend + # unnecessary information to the backend. Do the same with VIRTUAL_REF_*. if op.opnum == rop.ARRAYCOPY: descr = op.args[0] assert isinstance(descr, AbstractDescr) - return ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) - return op + op = ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) + elif op.opnum == rop.VIRTUAL_REF: + op = ResOperation(rop.SAME_AS, [op.args[0]], op.result) + elif op.opnum == rop.VIRTUAL_REF_FINISH: + return [] + return [op] def optimize_loop(metainterp_sd, old_loops, loop): if old_loops: @@ -35,7 +39,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, memo) newboxes = modifier.finish(EMPTY_VALUES) descr.store_final_boxes(op, newboxes) - newoperations.append(transform(op)) + newoperations.extend(transform(op)) loop.operations = newoperations return None Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/specnode.py Tue Jun 8 19:48:40 2010 @@ -57,7 +57,8 @@ from pypy.jit.metainterp import executor, history, resoperation for ofs, subspecnode in self.fields: assert isinstance(ofs, history.AbstractDescr) - fieldbox = executor.execute(cpu, resoperation.rop.GETFIELD_GC, + fieldbox = executor.execute(cpu, None, + resoperation.rop.GETFIELD_GC, ofs, valuebox) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -95,7 +96,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp import executor, history, resoperation for i in range(len(self.items)): - itembox = executor.execute(cpu, resoperation.rop.GETARRAYITEM_GC, + itembox = executor.execute(cpu, None, + resoperation.rop.GETARRAYITEM_GC, self.arraydescr, valuebox, history.ConstInt(i)) subspecnode = self.items[i] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/oparser.py Tue Jun 8 19:48:40 2010 @@ -4,10 +4,11 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\ - ConstAddr, ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ + ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ LoopToken from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.typesystem import llhelper +from pypy.jit.codewriter.heaptracker import adr2int from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llstr @@ -74,8 +75,7 @@ return ConstPtr(obj) else: assert typ == 'class' - return ConstAddr(llmemory.cast_ptr_to_adr(obj), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(obj))) else: if typ == 'ptr': return ConstObj(obj) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_basic.py Tue Jun 8 19:48:40 2010 @@ -4,30 +4,97 @@ from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp import support, codewriter, pyjitpl, history -from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy +from pypy.jit.metainterp import pyjitpl, history +from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy from pypy import conftest from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype -def _get_bare_metainterp(func, values, CPUClass, type_system, - listops=False): - from pypy.annotation.policy import AnnotatorPolicy - from pypy.annotation.model import lltype_to_annotation - from pypy.rpython.test.test_llinterp import gengraph +def _get_jitcodes(testself, CPUClass, func, values, type_system): + from pypy.jit.codewriter import support, codewriter + from pypy.jit.metainterp import simple_optimize - rtyper = support.annotate(func, values, type_system=type_system) + class FakeWarmRunnerState: + def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): + pass + + # pick the optimizer this way + optimize_loop = staticmethod(simple_optimize.optimize_loop) + optimize_bridge = staticmethod(simple_optimize.optimize_bridge) + + trace_limit = sys.maxint + debug_level = 2 + func._jit_unroll_safe_ = True + rtyper = support.annotate(func, values, type_system=type_system) + graphs = rtyper.annotator.translator.graphs stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - graphs = rtyper.annotator.translator.graphs - opt = history.Options(listops=listops) - metainterp_sd = pyjitpl.MetaInterpStaticData(graphs[0], cpu, stats, opt) - metainterp_sd.finish_setup(optimizer="bogus") + cw = codewriter.CodeWriter(cpu, graphs[0]) + testself.cw = cw + cw.find_all_graphs(JitPolicy()) + # + testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate.cpu = cpu + if hasattr(testself, 'finish_setup_for_interp_operations'): + testself.finish_setup_for_interp_operations() + # + cw.make_jitcodes(verbose=True) + +def _run_with_blackhole(testself, args): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + cw = testself.cw + blackholeinterpbuilder = BlackholeInterpBuilder(cw) + blackholeinterp = blackholeinterpbuilder.acquire_interp() + count_i = count_r = count_f = 0 + for value in args: + T = lltype.typeOf(value) + if T == lltype.Signed: + blackholeinterp.setarg_i(count_i, value) + count_i += 1 + elif T == llmemory.GCREF: + blackholeinterp.setarg_r(count_r, value) + count_r += 1 + elif T == lltype.Float: + blackholeinterp.setarg_f(count_f, value) + count_f += 1 + else: + raise TypeError(T) + blackholeinterp.setposition(cw.mainjitcode, 0) + blackholeinterp.run() + return blackholeinterp._final_result_anytype() + +def _run_with_pyjitpl(testself, args): + + class DoneWithThisFrame(Exception): + pass + + class DoneWithThisFrameRef(DoneWithThisFrame): + def __init__(self, cpu, *args): + DoneWithThisFrame.__init__(self, *args) + + cw = testself.cw + opt = history.Options(listops=True) + metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) + metainterp_sd.finish_setup(cw, optimizer="bogus") + metainterp_sd.state = testself.warmrunnerstate + metainterp_sd.state.cpu = metainterp_sd.cpu metainterp = pyjitpl.MetaInterp(metainterp_sd) - return metainterp, rtyper + metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame + metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef + metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame + testself.metainterp = metainterp + try: + metainterp.compile_and_run_once(*args) + except DoneWithThisFrame, e: + #if conftest.option.view: + # metainterp.stats.view() + return e.args[0] + else: + raise Exception("FAILED") + class JitMixin: basic = True @@ -63,56 +130,14 @@ return ll_meta_interp(*args, **kwds) def interp_operations(self, f, args, **kwds): - from pypy.jit.metainterp import simple_optimize - - class DoneWithThisFrame(Exception): - pass - - class DoneWithThisFrameRef(DoneWithThisFrame): - def __init__(self, cpu, *args): - DoneWithThisFrame.__init__(self, *args) - - class FakeWarmRunnerState: - def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): - pass - - # pick the optimizer this way - optimize_loop = staticmethod(simple_optimize.optimize_loop) - optimize_bridge = staticmethod(simple_optimize.optimize_bridge) - - trace_limit = sys.maxint - debug_level = 2 - - metainterp, rtyper = _get_bare_metainterp(f, args, self.CPUClass, - self.type_system, - **kwds) - metainterp.staticdata.state = FakeWarmRunnerState() - metainterp.staticdata.state.cpu = metainterp.staticdata.cpu - if hasattr(self, 'finish_metainterp_for_interp_operations'): - self.finish_metainterp_for_interp_operations(metainterp) - portal_graph = rtyper.annotator.translator.graphs[0] - cw = codewriter.CodeWriter(rtyper) - - graphs = cw.find_all_graphs(portal_graph, JitPolicy(), - self.CPUClass.supports_floats) - cw._start(metainterp.staticdata, None) - portal_graph.func._jit_unroll_safe_ = True - maingraph = cw.make_one_bytecode((portal_graph, None), False) - cw.finish_making_bytecodes() - metainterp.staticdata.portal_code = maingraph - metainterp.staticdata._class_sizes = cw.class_sizes - metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame - metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef - metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame - self.metainterp = metainterp - try: - metainterp.compile_and_run_once(*args) - except DoneWithThisFrame, e: - #if conftest.option.view: - # metainterp.stats.view() - return e.args[0] - else: - raise Exception("FAILED") + # get the JitCodes for the function f + _get_jitcodes(self, self.CPUClass, f, args, self.type_system) + # try to run it with blackhole.py + result1 = _run_with_blackhole(self, args) + # try to run it with pyjitpl.py + result2 = _run_with_pyjitpl(self, args) + assert result1 == result2 + return result1 def check_history(self, expected=None, **isns): # this can be used after calling meta_interp @@ -151,7 +176,7 @@ class OOJitMixin(JitMixin): type_system = 'ootype' - CPUClass = runner.OOtypeCPU + #CPUClass = runner.OOtypeCPU def setup_class(cls): py.test.skip("ootype tests skipped for now") @@ -204,9 +229,11 @@ from pypy.rlib.rarithmetic import r_uint def f(a, b): + a = r_uint(a) + b = r_uint(b) return a/b - res = self.interp_operations(f, [r_uint(4), r_uint(3)]) + res = self.interp_operations(f, [4, 3]) assert res == 1 def test_direct_call(self): @@ -339,6 +366,38 @@ assert res == 42 self.check_operations_history(int_add=0, int_mul=0, call=0) + def test_constfold_call_pure(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + n -= externfn(m) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + + def test_constfold_call_pure_2(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + class V: + def __init__(self, value): + self.value = value + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + v = V(m) + n -= externfn(v.value) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) class X(object): @@ -513,6 +572,39 @@ res = self.interp_operations(f, [15]) assert res == -1 + def test_int_add_ovf(self): + def f(x, y): + try: + return ovfcheck(x + y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -98 + res = self.interp_operations(f, [1, sys.maxint]) + assert res == -42 + + def test_int_sub_ovf(self): + def f(x, y): + try: + return ovfcheck(x - y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -102 + res = self.interp_operations(f, [1, -sys.maxint]) + assert res == -42 + + def test_int_mul_ovf(self): + def f(x, y): + try: + return ovfcheck(x * y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -200 + res = self.interp_operations(f, [-3, sys.maxint//2]) + assert res == -42 + def test_mod_ovf(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) def f(n, x, y): @@ -523,6 +615,7 @@ return n res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + self.check_loops(call=0) def test_abs(self): myjitdriver = JitDriver(greens = [], reds = ['i', 't']) @@ -581,10 +674,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) def test_bridge_from_interpreter_2(self): # one case for backend - computing of framesize on guard failure @@ -731,21 +823,26 @@ def test_zerodivisionerror(self): # test the case of exception-raising operation that is not delegated # to the backend at all: ZeroDivisionError - from pypy.rpython.lltypesystem.lloperation import llop # def f(n): + assert n >= 0 try: - return llop.int_mod_ovf_zer(lltype.Signed, 5, n) + return ovfcheck(5 % n) except ZeroDivisionError: return -666 + except OverflowError: + return -777 res = self.interp_operations(f, [0]) assert res == -666 # def f(n): + assert n >= 0 try: - return llop.int_floordiv_ovf_zer(lltype.Signed, 6, n) + return ovfcheck(6 // n) except ZeroDivisionError: return -667 + except OverflowError: + return -778 res = self.interp_operations(f, [0]) assert res == -667 @@ -795,7 +892,7 @@ assert not res def test_isinstance_2(self): - driver = JitDriver(greens = [], reds = ['x', 'n', 'sum']) + driver = JitDriver(greens = [], reds = ['n', 'sum', 'x']) class A: pass class B(A): @@ -836,7 +933,9 @@ return obj.a res = self.interp_operations(fn, [1]) assert res == 1 - self.check_operations_history(guard_class=0, instanceof=0) + self.check_operations_history(guard_class=0) + if self.type_system == 'ootype': + self.check_operations_history(instanceof=0) def test_r_dict(self): from pypy.rlib.objectmodel import r_dict @@ -1017,10 +1116,10 @@ def test_residual_external_call(self): import math - myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res']) def f(x, y): x = float(x) - res = 0 + res = 0.0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) @@ -1259,7 +1358,7 @@ self.check_loops(call=1) def test_bug_optimizeopt_mutates_ops(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'a', 'const']) + myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a']) class A(object): pass class B(A): @@ -1326,6 +1425,16 @@ # this checks that the logic triggered by make_a_counter_per_value() # works and prevents generating tons of bridges + def test_swap_values(self): + def f(x, y): + if x > 5: + x, y = y, x + return x - y + res = self.interp_operations(f, [10, 2]) + assert res == -8 + res = self.interp_operations(f, [3, 2]) + assert res == 1 + class TestOOtype(BasicTests, OOJitMixin): @@ -1426,33 +1535,47 @@ from pypy.rpython.lltypesystem import lltype TP = lltype.Struct('x') - def f(p1, p2): + def f(i1, i2): + p1 = prebuilt[i1] + p2 = prebuilt[i2] a = p1 is p2 b = p1 is not p2 c = bool(p1) d = not bool(p2) return 1000*a + 100*b + 10*c + d - x = lltype.malloc(TP, flavor='raw') - expected = f(x, x) - assert self.interp_operations(f, [x, x]) == expected - lltype.free(x, flavor='raw') + prebuilt = [lltype.malloc(TP, flavor='raw')] * 2 + expected = f(0, 1) + assert self.interp_operations(f, [0, 1]) == expected def test_casts(self): + py.test.skip("xxx fix or kill") if not self.basic: py.test.skip("test written in a style that " "means it's frontend only") - from pypy.rpython.lltypesystem import lltype, llmemory - - TP = lltype.GcStruct('x') + from pypy.rpython.lltypesystem import lltype, llmemory, rffi + + TP = lltype.GcStruct('S1') def f(p): n = lltype.cast_ptr_to_int(p) return n - x = lltype.malloc(TP) - res = self.interp_operations(f, [x]) - expected = self.metainterp.cpu.do_cast_ptr_to_int( - history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))).value - assert res == expected + xref = lltype.cast_opaque_ptr(llmemory.GCREF, x) + res = self.interp_operations(f, [xref]) + y = llmemory.cast_ptr_to_adr(x) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) + # + TP = lltype.Struct('S2') + prebuilt = [lltype.malloc(TP, immortal=True), + lltype.malloc(TP, immortal=True)] + def f(x): + p = prebuilt[x] + n = lltype.cast_ptr_to_int(p) + return n + res = self.interp_operations(f, [1]) + y = llmemory.cast_ptr_to_adr(prebuilt[1]) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) def test_collapsing_ptr_eq(self): S = lltype.GcStruct('S') Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_blackhole.py Tue Jun 8 19:48:40 2010 @@ -1,87 +1,211 @@ +import py from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp import pyjitpl +from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder +from pypy.jit.metainterp.blackhole import BlackholeInterpreter +from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl +from pypy.jit.metainterp import history, pyjitpl +from pypy.jit.codewriter.assembler import JitCode +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.llinterp import LLException -class BlackholeTests(object): - - def meta_interp(self, *args): - def counting_init(frame, metainterp, jitcode, greenkey=None): - previnit(frame, metainterp, jitcode, greenkey) - self.seen_frames.append(jitcode.name) +class FakeCodeWriter: + pass +class FakeAssembler: + pass +class FakeCPU: + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert func == 321 + assert calldescr == "" + if args_i[0] < 0: + raise LLException("etype", "evalue") + return args_i[0] * 2 + +def getblackholeinterp(insns, descrs=[]): + cw = FakeCodeWriter() + cw.cpu = FakeCPU() + cw.assembler = FakeAssembler() + cw.assembler.insns = insns + cw.assembler.descrs = descrs + builder = BlackholeInterpBuilder(cw) + return builder.acquire_interp() + +def test_simple(): + jitcode = JitCode("test") + jitcode.setup("\x00\x00\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_add/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0, 40) + blackholeinterp.setarg_i(1, 2) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_const(): + jitcode = JitCode("test") + jitcode.setup("\x00\x30\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_sub/ci>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 6) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_bigconst(): + jitcode = JitCode("test") + jitcode.setup("\x00\xFD\x01\x02" + "\x01\x02", + [666, 666, 10042, 666]) + blackholeinterp = getblackholeinterp({'int_sub/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 10000) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_loop(): + jitcode = JitCode("test") + jitcode.setup("\x00\x16\x02\x10\x00" # L1: goto_if_not_int_gt %i0, 2, L2 + "\x01\x17\x16\x17" # int_add %i1, %i0, %i1 + "\x02\x16\x01\x16" # int_sub %i0, $1, %i0 + "\x03\x00\x00" # goto L1 + "\x04\x17", # L2: int_return %i1 + []) + blackholeinterp = getblackholeinterp({'goto_if_not_int_gt/icL': 0, + 'int_add/ii>i': 1, + 'int_sub/ic>i': 2, + 'goto/L': 3, + 'int_return/i': 4}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x16, 6) # %i0 + blackholeinterp.setarg_i(0x17, 100) # %i1 + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 100+6+5+4+3 + +def test_simple_exception(): + jitcode = JitCode("test") + jitcode.setup( # residual_call_ir_i $<* fn g>, , I[%i9], R[], %i8 + "\x01\xFF\x00\x00\x01\x09\x00\x08" + "\x00\x0D\x00" # catch_exception L1 + "\x02\x08" # int_return %i8 + "\x03\x2A", # L1: int_return $42 + [321]) # <-- address of the function g + blackholeinterp = getblackholeinterp({'catch_exception/L': 0, + 'residual_call_ir_i/idIR>i': 1, + 'int_return/i': 2, + 'int_return/c': 3}, + [""]) + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, 100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 200 + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, -100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_convert_and_run_from_pyjitpl(): + class MyMIFrame: + jitcode = JitCode("test") + jitcode.setup("\xFF" # illegal instruction + "\x00\x00\x01\x02" # int_add/ii>i + "\x01\x02", # int_return/i + [], + num_regs_i=3, num_regs_r=0, num_regs_f=0) + pc = 1 + registers_i = [history.BoxInt(40), history.ConstInt(2), None] + class MyMetaInterp: + class staticdata: + result_type = 'int' + class profiler: + @staticmethod + def start_blackhole(): pass + @staticmethod + def end_blackhole(): pass + class DoneWithThisFrameInt(Exception): + pass + last_exc_value_box = None + framestack = [MyMIFrame()] + MyMetaInterp.staticdata.blackholeinterpbuilder = getblackholeinterp( + {'int_add/ii>i': 0, 'int_return/i': 1}).builder + MyMetaInterp.staticdata.blackholeinterpbuilder.metainterp_sd = \ + MyMetaInterp.staticdata + # + d = py.test.raises(MyMetaInterp.staticdata.DoneWithThisFrameInt, + convert_and_run_from_pyjitpl, MyMetaInterp()) + assert d.value.args == (42,) + + +class TestBlackhole(LLJitMixin): + + def test_blackholeinterp_cache(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + def choices(x): + if x == 2: return 10 + if x == 3: return 199 + if x == 4: return 124 + if x == 5: return -521 + if x == 6: return 8917 + if x == 7: return -387 + return 34871 + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + y += choices(x) + x -= 1 + return y # - previnit = pyjitpl.MIFrame.__init__.im_func + seen = [] + def my_copy_constants(self, *args): + seen.append(1) + return org_copy_constants(self, *args) + org_copy_constants = BlackholeInterpreter.copy_constants + BlackholeInterpreter.copy_constants = my_copy_constants try: - self.seen_frames = [] - pyjitpl.MIFrame.__init__ = counting_init - return super(BlackholeTests, self).meta_interp(*args) + res = self.meta_interp(f, [7], repeat=7) finally: - pyjitpl.MIFrame.__init__ = previnit - - def test_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - return g() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_indirect_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - call = h - else: - call = g - return call() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_oosends_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - class A: - def meth(self): - return 42 - class B(A): - def meth(self): - return 45 - class C(A): - def meth(self): - return 64 - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - x = B() - else: - x = C() - return x.meth() - res = self.meta_interp(f, [7]) - assert res == 64 - assert self.seen_frames == ['f', 'f'] - - -class TestLLtype(BlackholeTests, LLJitMixin): - pass - -class TestOOtype(BlackholeTests, OOJitMixin): - pass + BlackholeInterpreter.copy_constants = org_copy_constants + # + assert res == sum([choices(x) for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 + assert len(seen) == 2 * 3 + + def test_blackholeinterp_cache_exc(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + class FooError(Exception): + def __init__(self, num): + self.num = num + def choices(x): + if x == 2: raise FooError(10) + if x == 3: raise FooError(199) + if x == 4: raise FooError(124) + if x == 5: raise FooError(-521) + if x == 6: raise FooError(8917) + if x == 7: raise FooError(-387) + raise FooError(34871) + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + try: + choices(x) + except FooError, e: + y += e.num + x -= 1 + return y + res = self.meta_interp(f, [7], repeat=7) + assert res == sum([py.test.raises(FooError, choices, x).value.num + for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_compile.py Tue Jun 8 19:48:40 2010 @@ -2,7 +2,8 @@ from pypy.jit.metainterp.history import BoxInt from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop -from pypy.jit.metainterp.compile import ResumeGuardDescr, ResumeGuardCounters +from pypy.jit.metainterp.compile import ResumeGuardDescr +from pypy.jit.metainterp.compile import ResumeGuardCountersInt from pypy.jit.metainterp import optimize, jitprof, typesystem from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin @@ -107,49 +108,49 @@ def test_resume_guard_counters(): - rgc = ResumeGuardCounters() + rgc = ResumeGuardCountersInt() # fill in the table for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 1 - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 2 assert rgc.counters == [0] * (4-i) + [2] * (1+i) for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 3 # make a distribution: [5, 4, 7, 6, 3] assert rgc.counters == [3, 3, 3, 3, 3] - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 4 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 5 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 4 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 5 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 7 - count = rgc.see(BoxInt(103)) + count = rgc.see_int(103) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 5 assert rgc.counters == [5, 4, 7, 6, 3] # the next new item should throw away 104, as 5 is the middle counter - count = rgc.see(BoxInt(190)) + count = rgc.see_int(190) assert count == 1 assert rgc.counters == [1, 4, 7, 6, 3] # the next new item should throw away 103, as 4 is the middle counter - count = rgc.see(BoxInt(191)) + count = rgc.see_int(191) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 3] # the next new item should throw away 100, as 3 is the middle counter - count = rgc.see(BoxInt(192)) + count = rgc.see_int(192) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 1] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_exception.py Tue Jun 8 19:48:40 2010 @@ -2,7 +2,7 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy class ExceptionTests: @@ -516,11 +516,10 @@ assert res == -1 self.check_tree_loop_count(2) # the loop and the entry path # we get: - # ENTER - compile the new loop - # ENTER (BlackHole) - leave - # ENTER - compile the entry bridge - # ENTER - compile the leaving path (raising MyError) - self.check_enter_count(4) + # ENTER - compile the new loop + # ENTER - compile the entry bridge + # ENTER - compile the leaving path (raising MyError) + self.check_enter_count(3) def test_bridge_from_interpreter_exc_2(self): @@ -556,7 +555,6 @@ optimizer=OPTIMIZER_SIMPLE) assert res == 8 - def test_overflowerror_escapes(self): def g(x): return ovfcheck(x + 1) @@ -570,6 +568,26 @@ res = self.interp_operations(f, [sys.maxint]) assert res == -42 + def test_bug_1(self): + def h(i): + if i > 10: + raise ValueError + if i > 5: + raise KeyError + return 5 + def g(i): + try: + return h(i) + except ValueError: + return 21 + def f(i): + try: + return g(i) + except KeyError: + return 42 + res = self.interp_operations(f, [99]) + assert res == 21 + class MyError(Exception): def __init__(self, n): self.n = n Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_executor.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_executor.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_executor.py Tue Jun 8 19:48:40 2010 @@ -1,60 +1,87 @@ import py import sys, random from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.jit.metainterp.executor import make_execute_list, execute +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.executor import execute_varargs, execute_nonspec from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat from pypy.jit.metainterp.history import AbstractDescr, Box +from pypy.jit.metainterp import history from pypy.jit.backend.model import AbstractCPU class FakeDescr(AbstractDescr): pass -class FakeBox(Box): +class FakeCallDescr(FakeDescr): + def get_return_type(self): + return history.FLOAT + +class FakeFieldDescr(FakeDescr): + def is_pointer_field(self): + return False + def is_float_field(self): + return True + +class FakeArrayDescr(FakeDescr): + def is_array_of_pointers(self): + return False + def is_array_of_floats(self): + return True + +class FakeResultR: + _TYPE = llmemory.GCREF def __init__(self, *args): - self.args = args + self.fakeargs = args + +class FakeMetaInterp: + pass class FakeCPU(AbstractCPU): supports_floats = True - def do_new(self, descr): - return FakeBox('new', descr) - - def do_arraylen_gc(self, box1, descr): - return FakeBox('arraylen_gc', box1, descr) - - def do_setfield_gc(self, box1, box2, descr): - return FakeBox('setfield_gc', box1, box2, descr) + def bh_new(self, descr): + return FakeResultR('new', descr) - def do_setarrayitem_gc(self, box1, box2, box3, descr): - return FakeBox('setarrayitem_gc', box1, box2, box3, descr) + def bh_arraylen_gc(self, descr, array): + assert not array + assert isinstance(descr, FakeDescr) + return 55 + + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + self.fakesetfield = (struct, newvalue, fielddescr) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + self.fakesetarrayitem = (array, index, newvalue, arraydescr) + + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self.fakecalled = (func, calldescr, args_i, args_r, args_f) + return 42.5 - def do_call(self, args, descr): - return FakeBox('call', args, descr) - - def do_strsetitem(self, box1, box2, box3): - return FakeBox('strsetitem', box1, box2, box3) - -make_execute_list(FakeCPU) + def bh_strsetitem(self, string, index, newvalue): + self.fakestrsetitem = (string, index, newvalue) def test_execute(): cpu = FakeCPU() descr = FakeDescr() - box = execute(cpu, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) + box = execute(cpu, None, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) assert box.value == 42 - box = execute(cpu, rop.NEW, descr) - assert box.args == ('new', descr) + box = execute(cpu, None, rop.NEW, descr) + assert box.value.fakeargs == ('new', descr) def test_execute_varargs(): cpu = FakeCPU() - descr = FakeDescr() - argboxes = [BoxInt(321), ConstInt(123)] - box = execute_varargs(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + descr = FakeCallDescr() + argboxes = [BoxInt(99999), BoxInt(321), ConstFloat(2.25), ConstInt(123), + BoxPtr(), BoxFloat(5.5)] + box = execute_varargs(cpu, FakeMetaInterp(), rop.CALL, argboxes, descr) + assert box.value == 42.5 + assert cpu.fakecalled == (99999, descr, [321, 123], + [ConstPtr.value], [2.25, 5.5]) def test_execute_nonspec(): cpu = FakeCPU() @@ -62,33 +89,38 @@ # cases with a descr # arity == -1 argboxes = [BoxInt(321), ConstInt(123)] - box = execute_nonspec(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + box = execute_nonspec(cpu, FakeMetaInterp(), rop.CALL, + argboxes, FakeCallDescr()) + assert box.value == 42.5 # arity == 0 - box = execute_nonspec(cpu, rop.NEW, [], descr) - assert box.args == ('new', descr) + box = execute_nonspec(cpu, None, rop.NEW, [], descr) + assert box.value.fakeargs == ('new', descr) # arity == 1 - box1 = BoxInt(515) - box = execute_nonspec(cpu, rop.ARRAYLEN_GC, [box1], descr) - assert box.args == ('arraylen_gc', box1, descr) + box1 = BoxPtr() + box = execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr) + assert box.value == 55 # arity == 2 - box2 = BoxInt(222) - box = execute_nonspec(cpu, rop.SETFIELD_GC, [box1, box2], descr) - assert box.args == ('setfield_gc', box1, box2, descr) + box2 = BoxFloat(222.2) + fielddescr = FakeFieldDescr() + execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr) + assert cpu.fakesetfield == (box1.value, box2.value, fielddescr) # arity == 3 - box3 = BoxInt(-33) - box = execute_nonspec(cpu, rop.SETARRAYITEM_GC, [box1, box2, box3], descr) - assert box.args == ('setarrayitem_gc', box1, box2, box3, descr) + box3 = BoxInt(33) + arraydescr = FakeArrayDescr() + execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2], + arraydescr) + assert cpu.fakesetarrayitem == (box1.value, box3.value, box2.value, + arraydescr) # cases without descr # arity == 1 - box = execute_nonspec(cpu, rop.INT_INVERT, [box1]) - assert box.value == ~515 + box = execute_nonspec(cpu, None, rop.INT_INVERT, [box3]) + assert box.value == ~33 # arity == 2 - box = execute_nonspec(cpu, rop.INT_LSHIFT, [box1, BoxInt(3)]) - assert box.value == 515 << 3 + box = execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, BoxInt(3)]) + assert box.value == 33 << 3 # arity == 3 - box = execute_nonspec(cpu, rop.STRSETITEM, [box1, box2, box3]) - assert box.args == ('strsetitem', box1, box2, box3) + execute_nonspec(cpu, None, rop.STRSETITEM, [box1, BoxInt(3), box3]) + assert cpu.fakestrsetitem == (box1.value, 3, box3.value) # ints @@ -181,7 +213,7 @@ (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]), (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]), (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]), - (rop.BOOL_NOT, [(0, 1), (1, 0)]), + (rop.INT_IS_ZERO, [(0, 1), (1, 0), (2, 0), (-1, 0), (minint, 0)]), ]: for x, y in testcases: yield opnum, [x], y @@ -204,7 +236,7 @@ def test_int_ops(): cpu = FakeCPU() for opnum, boxargs, retvalue in get_int_tests(): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) assert box.getint() == retvalue # floats @@ -242,9 +274,6 @@ yield (rop.FLOAT_NEG, [15.9], 'float', -15.9) yield (rop.FLOAT_ABS, [-5.9], 'float', 5.9) yield (rop.FLOAT_ABS, [15.9], 'float', 15.9) - yield (rop.FLOAT_IS_TRUE, [-5.9], 'int', 1) - yield (rop.FLOAT_IS_TRUE, [0.0], 'int', 0) - yield (rop.FLOAT_IS_TRUE, [-0.0], 'int', 0) yield (rop.CAST_FLOAT_TO_INT, [-5.9], 'int', -5) yield (rop.CAST_FLOAT_TO_INT, [5.9], 'int', 5) yield (rop.CAST_INT_TO_FLOAT, [123], 'float', 123.0) @@ -276,7 +305,7 @@ def test_float_ops(): cpu = FakeCPU() for opnum, boxargs, rettype, retvalue in get_float_tests(cpu): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) if rettype == 'float': assert box.getfloat() == retvalue elif rettype == 'int': Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_history.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_history.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_history.py Tue Jun 8 19:48:40 2010 @@ -9,10 +9,3 @@ s = lltype.cast_pointer(lltype.Ptr(S), t) const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)) assert const._getrepr_() == "*T" - -def test_slicing(): - h = History() - h.operations = [1, 2, 3, 4, 5] - rest = h.slice_history_at(2) - assert rest == [4, 5] - assert h.operations == [1, 2] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_jitprof.py Tue Jun 8 19:48:40 2010 @@ -63,7 +63,7 @@ ] assert profiler.events == expected assert profiler.times == [2, 1, 1, 1] - assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0, + assert profiler.counters == [1, 1, 1, 1, 3, 3, 1, 7, 1, 0, 0, 0, 0, 0, 0, 0] def test_simple_loop_with_call(self): @@ -84,8 +84,8 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[1, 0], [1, 0], [0, 0]] + # calls = (executed, recorded) x (inpure, pure) + assert profiler.calls == [[1, 0], [1, 0]] def test_blackhole_pure(self): @purefunction @@ -99,12 +99,11 @@ myjitdriver.can_enter_jit(x=x, y=y, res=res, z=z) myjitdriver.jit_merge_point(x=x, y=y, res=res, z=z) res += x - if y == 1: - res += g(z) + res += g(z) y -= 1 return res * 2 res = self.meta_interp(f, [6, 7, 2]) - assert res == 90 + assert res == f(6, 7, 2) profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[0, 1], [0, 0], [0, 1]] + # calls = (executed, recorded) x (inpure, pure) + assert profiler.calls == [[0, 1], [0, 0]] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_list.py Tue Jun 8 19:48:40 2010 @@ -1,7 +1,5 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_loop.py Tue Jun 8 19:48:40 2010 @@ -4,7 +4,7 @@ from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import history @@ -342,7 +342,7 @@ assert res == expected def test_loop_unicode(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = u'' while n > 13: @@ -356,7 +356,7 @@ assert res == expected def test_loop_string(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = '' while n > 13: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizefindnode.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizefindnode.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizefindnode.py Tue Jun 8 19:48:40 2010 @@ -6,7 +6,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - Const, ConstAddr, TreeLoop, BoxObj, + Const, TreeLoop, BoxObj, ConstObj, AbstractDescr) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder @@ -16,7 +16,8 @@ from pypy.jit.metainterp.specnode import VirtualArraySpecNode from pypy.jit.metainterp.specnode import VirtualStructSpecNode from pypy.jit.metainterp.specnode import ConstantSpecNode -from pypy.jit.metainterp.effectinfo import EffectInfo +from pypy.jit.codewriter.effectinfo import EffectInfo +from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int from pypy.jit.metainterp.test.oparser import parse def test_sort_descrs(): @@ -113,7 +114,7 @@ EffectInfo([adescr], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], - forces_virtual_or_virtualizable=True)) + EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)) class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though @@ -129,83 +130,81 @@ jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) - cpu.class_sizes = { - cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE), - cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2), - cpu.cast_adr_to_int(u_vtable_adr): cpu.sizeof(U), - cpu.cast_adr_to_int(jvr_vtable_adr): cpu.sizeof( - vrefinfo.JIT_VIRTUAL_REF), - } + register_known_gctype(cpu, node_vtable, NODE) + register_known_gctype(cpu, node_vtable2, NODE2) + register_known_gctype(cpu, u_vtable, U) + register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF) + namespace = locals() -class OOtypeMixin(object): +class OOtypeMixin_xxx_disabled(object): type_system = 'ootype' - def get_class_of_box(self, box): - root = box.getref(ootype.ROOT) - return ootype.classof(root) +## def get_class_of_box(self, box): +## root = box.getref(ootype.ROOT) +## return ootype.classof(root) - cpu = runner.OOtypeCPU(None) - NODE = ootype.Instance('NODE', ootype.ROOT, {}) - NODE._add_fields({'value': ootype.Signed, - 'floatval' : ootype.Float, - 'next': NODE}) - NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) - - node_vtable = ootype.runtimeClass(NODE) - node_vtable_adr = ootype.cast_to_object(node_vtable) - node_vtable2 = ootype.runtimeClass(NODE2) - node_vtable_adr2 = ootype.cast_to_object(node_vtable2) - - node = ootype.new(NODE) - nodebox = BoxObj(ootype.cast_to_object(node)) - myptr = nodebox.value - myptr2 = ootype.cast_to_object(ootype.new(NODE)) - nodebox2 = BoxObj(ootype.cast_to_object(node)) - valuedescr = cpu.fielddescrof(NODE, 'value') - floatdescr = cpu.fielddescrof(NODE, 'floatval') - nextdescr = cpu.fielddescrof(NODE, 'next') - otherdescr = cpu.fielddescrof(NODE2, 'other') - nodesize = cpu.typedescrof(NODE) - nodesize2 = cpu.typedescrof(NODE2) - - arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) - floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) - - # a plain Record - S = ootype.Record({'a': ootype.Signed, 'b': NODE}) - ssize = cpu.typedescrof(S) - adescr = cpu.fielddescrof(S, 'a') - bdescr = cpu.fielddescrof(S, 'b') - sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) - arraydescr2 = cpu.arraydescrof(ootype.Array(S)) - - T = ootype.Record({'c': ootype.Signed, - 'd': ootype.Array(NODE)}) - tsize = cpu.typedescrof(T) - cdescr = cpu.fielddescrof(T, 'c') - ddescr = cpu.fielddescrof(T, 'd') - arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) - - U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) - usize = cpu.typedescrof(U) - onedescr = cpu.fielddescrof(U, 'one') - u_vtable = ootype.runtimeClass(U) - u_vtable_adr = ootype.cast_to_object(u_vtable) - - # force a consistent order - valuedescr.sort_key() - nextdescr.sort_key() - adescr.sort_key() - bdescr.sort_key() - - FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) - nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype - - cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), - node_vtable_adr2: cpu.typedescrof(NODE2), - u_vtable_adr: cpu.typedescrof(U)} - namespace = locals() +## cpu = runner.OOtypeCPU(None) +## NODE = ootype.Instance('NODE', ootype.ROOT, {}) +## NODE._add_fields({'value': ootype.Signed, +## 'floatval' : ootype.Float, +## 'next': NODE}) +## NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) + +## node_vtable = ootype.runtimeClass(NODE) +## node_vtable_adr = ootype.cast_to_object(node_vtable) +## node_vtable2 = ootype.runtimeClass(NODE2) +## node_vtable_adr2 = ootype.cast_to_object(node_vtable2) + +## node = ootype.new(NODE) +## nodebox = BoxObj(ootype.cast_to_object(node)) +## myptr = nodebox.value +## myptr2 = ootype.cast_to_object(ootype.new(NODE)) +## nodebox2 = BoxObj(ootype.cast_to_object(node)) +## valuedescr = cpu.fielddescrof(NODE, 'value') +## floatdescr = cpu.fielddescrof(NODE, 'floatval') +## nextdescr = cpu.fielddescrof(NODE, 'next') +## otherdescr = cpu.fielddescrof(NODE2, 'other') +## nodesize = cpu.typedescrof(NODE) +## nodesize2 = cpu.typedescrof(NODE2) + +## arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) +## floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) + +## # a plain Record +## S = ootype.Record({'a': ootype.Signed, 'b': NODE}) +## ssize = cpu.typedescrof(S) +## adescr = cpu.fielddescrof(S, 'a') +## bdescr = cpu.fielddescrof(S, 'b') +## sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) +## arraydescr2 = cpu.arraydescrof(ootype.Array(S)) + +## T = ootype.Record({'c': ootype.Signed, +## 'd': ootype.Array(NODE)}) +## tsize = cpu.typedescrof(T) +## cdescr = cpu.fielddescrof(T, 'c') +## ddescr = cpu.fielddescrof(T, 'd') +## arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) + +## U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) +## usize = cpu.typedescrof(U) +## onedescr = cpu.fielddescrof(U, 'one') +## u_vtable = ootype.runtimeClass(U) +## u_vtable_adr = ootype.cast_to_object(u_vtable) + +## # force a consistent order +## valuedescr.sort_key() +## nextdescr.sort_key() +## adescr.sort_key() +## bdescr.sort_key() + +## FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) +## nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype + +## cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), +## node_vtable_adr2: cpu.typedescrof(NODE2), +## u_vtable_adr: cpu.typedescrof(U)} +## namespace = locals() class BaseTest(object): invent_fail_descr = None @@ -220,8 +219,7 @@ # def constclass(cls_vtable): if self.type_system == 'lltype': - return ConstAddr(llmemory.cast_ptr_to_adr(cls_vtable), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable))) else: return ConstObj(ootype.cast_to_object(cls_vtable)) def constant(value): @@ -357,7 +355,7 @@ assert not boxp2.fromstart assert boxp1.knownclsbox is None - assert boxp2.knownclsbox.value == self.node_vtable_adr + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr def test_find_nodes_new_2(self): ops = """ @@ -413,8 +411,8 @@ assert not boxp2.fromstart assert not boxp3.fromstart - assert boxp2.knownclsbox.value == self.node_vtable_adr - assert boxp3.knownclsbox.value == self.node_vtable_adr2 + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr + assert boxp3.knownclsbox.getaddr() == self.node_vtable_adr2 def test_find_nodes_new_aliasing_0(self): ops = """ @@ -503,31 +501,31 @@ nextdescr=Virtual(node_vtable, nextdescr=Virtual(node_vtable)))''') - def test_find_nodes_oois(self): + def test_find_nodes_ptr_eq(self): ops = """ [p3, p4, p2] p0 = new_with_vtable(ConstClass(node_vtable)) p1 = new_with_vtable(ConstClass(node_vtable)) guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -1160,14 +1158,13 @@ class TestLLtype(BaseTestOptimizeFindNode, LLtypeMixin): pass -class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): - - def test_find_nodes_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - boxes, getnode = self.find_nodes(ops, 'Not') - assert not getnode(boxes.p0).escaped +##class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): +## def test_find_nodes_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## boxes, getnode = self.find_nodes(ops, 'Not') +## assert not getnode(boxes.p0).escaped Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_optimizeopt.py Tue Jun 8 19:48:40 2010 @@ -1,8 +1,7 @@ import py from pypy.rlib.objectmodel import instantiate -from pypy.jit.metainterp.test.test_resume import MyMetaInterp from pypy.jit.metainterp.test.test_optimizefindnode import (LLtypeMixin, - OOtypeMixin, + #OOtypeMixin, BaseTest) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp import optimizeopt @@ -10,18 +9,17 @@ from pypy.jit.metainterp.optimizeutil import InvalidLoop from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from pypy.jit.metainterp.jitprof import EmptyProfiler -from pypy.jit.metainterp import executor, compile, resume +from pypy.jit.metainterp import executor, compile, resume, history from pypy.jit.metainterp.resoperation import rop, opname, ResOperation from pypy.jit.metainterp.test.oparser import pure_parse -class FakeFrame(object): - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - - def __init__(self, code="", pc=0, exc_target=-1): - self.jitcode = code - self.pc = pc - self.exception_target = exc_target +##class FakeFrame(object): +## parent_resumedata_snapshot = None +## parent_resumedata_frame_info_list = None + +## def __init__(self, code="", pc=0): +## self.jitcode = code +## self.pc = pc class Fake(object): failargs_limit = 1000 @@ -45,9 +43,8 @@ fdescr = ResumeGuardDescr(None, None) op = ResOperation(rop.GUARD_TRUE, [], None, descr=fdescr) # setup rd data - fi0 = resume.FrameInfo(None, FakeFrame("code0", 1, 2)) - fdescr.rd_frame_info_list = resume.FrameInfo(fi0, - FakeFrame("code1", 3, -1)) + fi0 = resume.FrameInfo(None, "code0", 11) + fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) snapshot0 = resume.Snapshot(None, [b0]) fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1]) # @@ -215,14 +212,18 @@ def __eq__(self, other): return type(self) is type(other) # xxx obscure +def _sortboxes(boxes): + _kind2count = {history.INT: 1, history.REF: 2, history.FLOAT: 3} + return sorted(boxes, key=lambda box: _kind2count[box.type]) + class BaseTestOptimizeOpt(BaseTest): def invent_fail_descr(self, fail_args): if fail_args is None: return None descr = Storage() - descr.rd_frame_info_list = resume.FrameInfo(None, FakeFrame()) - descr.rd_snapshot = resume.Snapshot(None, fail_args) + descr.rd_frame_info_list = resume.FrameInfo(None, "code", 11) + descr.rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args)) return descr def assert_equal(self, optimized, expected): @@ -273,7 +274,7 @@ i0 = int_add(2, 3) i1 = int_is_true(i0) guard_true(i1) [] - i2 = bool_not(i1) + i2 = int_is_zero(i1) guard_false(i2) [] guard_value(i0, 5) [] jump() @@ -289,7 +290,7 @@ from pypy.jit.metainterp.executor import execute_nonspec from pypy.jit.metainterp.history import BoxInt import random - for opnum in range(rop.INT_ADD, rop.BOOL_NOT+1): + for opnum in range(rop.INT_ADD, rop.SAME_AS+1): try: op = opname[opnum] except KeyError: @@ -309,7 +310,7 @@ jump() """ % (op.lower(), ', '.join(map(str, args))) argboxes = [BoxInt(a) for a in args] - expected_value = execute_nonspec(self.cpu, opnum, + expected_value = execute_nonspec(self.cpu, None, opnum, argboxes).getint() expected = """ [] @@ -410,7 +411,7 @@ self.optimize_loop(ops, 'Not', expected) def test_int_is_true_1(self): - py.test.skip("too bad") + py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -427,6 +428,24 @@ """ self.optimize_loop(ops, 'Not', expected) + def test_int_is_true_is_zero(self): + py.test.skip("XXX implement me") + ops = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + expected = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + self.optimize_loop(ops, 'Not', expected) + def test_ooisnull_oononnull_2(self): ops = """ [p0] @@ -478,13 +497,13 @@ ops = """ [p0] guard_class(p0, ConstClass(node_vtable)) [] - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] jump(p0) """ @@ -499,13 +518,13 @@ ops = """ [p0] setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] guard_nonnull(p0) [] jump(p0) @@ -728,25 +747,25 @@ ops = """ [p0, p1, p2] guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -766,17 +785,17 @@ expected2 = """ [p0, p1, p2] guard_nonnull(p0) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -870,7 +889,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, NULL, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -886,7 +905,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, ConstPtr(myptr), descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -1514,7 +1533,7 @@ """ expected = """ [p1, i2, i3] - guard_true(i3) [p1, i2] + guard_true(i3) [i2, p1] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) @@ -1920,7 +1939,7 @@ ops = """ [p1] guard_class(p1, ConstClass(node_vtable2)) [] - i = ooisnot(ConstPtr(myptr), p1) + i = ptr_ne(ConstPtr(myptr), p1) guard_true(i) [] jump(p1) """ @@ -1936,9 +1955,9 @@ [p0] p1 = getfield_gc(p0, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) guard_true(i1) [] - i2 = ooisnot(p1, p2) + i2 = ptr_ne(p1, p2) guard_false(i2) [] jump(p0) """ @@ -1952,8 +1971,8 @@ def test_remove_duplicate_pure_op(self): ops = """ [p1, p2] - i1 = oois(p1, p2) - i2 = oois(p1, p2) + i1 = ptr_eq(p1, p2) + i2 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -1968,7 +1987,7 @@ """ expected = """ [p1, p2] - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -2024,7 +2043,7 @@ # typically called twice, before and after optimization if self.oparse is None: fdescr.rd_frame_info_list = resume.FrameInfo(None, - FakeFrame()) + "code", 11) fdescr.rd_snapshot = resume.Snapshot(None, fail_args) self.oparse = oparse # @@ -2096,7 +2115,7 @@ for pvar, pfieldname, pfieldvar in pendingfields: box = oparse.getvar(pvar) fielddescr = self.namespace[pfieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, box) @@ -2114,13 +2133,13 @@ if tag[0] in ('virtual', 'vstruct'): fieldname, fieldvalue = fieldtext.split('=') fielddescr = self.namespace[fieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, resolved) elif tag[0] == 'varray': fieldvalue = fieldtext - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETARRAYITEM_GC, tag[1], resolved, ConstInt(index)) @@ -2130,12 +2149,14 @@ index += 1 def check_expanded_fail_descr(self, expectedtext, guard_opnum): + from pypy.jit.metainterp.test.test_resume import ResumeDataFakeReader + from pypy.jit.metainterp.test.test_resume import MyMetaInterp guard_op, = [op for op in self.loop.operations if op.is_guard()] fail_args = guard_op.fail_args fdescr = guard_op.descr assert fdescr.guard_opnum == guard_opnum - reader = resume.ResumeDataReader(fdescr, fail_args, - MyMetaInterp(self.cpu)) + reader = ResumeDataFakeReader(fdescr, fail_args, + MyMetaInterp(self.cpu)) boxes = reader.consume_boxes() self._verify_fail_args(boxes, fdescr.oparse, expectedtext) @@ -2190,7 +2211,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p3, descr=nextdescr) - guard_true(i1, descr=fdescr) [p1, i3] + guard_true(i1, descr=fdescr) [i3, p1] jump(i2, i1, i3, p3) """ expected = """ @@ -2199,15 +2220,14 @@ jump(i2, 1, i3, p3) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3 + self.check_expanded_fail_descr('''i3, p1 where p1 is a node_vtable, valuedescr=1, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p3 ''', rop.GUARD_TRUE) def test_expand_fail_4(self): - for arg in ['p1', 'p1,i2', 'i2,p1', 'p1,p2', 'p2,p1', - 'p1,p2,i2', 'p1,i2,p2', 'p2,p1,i2', - 'p2,i2,p1', 'i2,p1,p2', 'i2,p2,p1']: + for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1', + 'i2,p1,p2', 'i2,p2,p1']: self.make_fail_descr() ops = """ [i1, i2, i3] @@ -2218,7 +2238,7 @@ setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) - guard_true(i1, descr=fdescr) [i4, %s, i3] + guard_true(i1, descr=fdescr) [i4, i3, %s] jump(i1, i2, i3) """ expected = """ @@ -2227,7 +2247,7 @@ jump(1, i2, i3) """ self.optimize_loop(ops % arg, 'Not, Not, Not', expected) - self.check_expanded_fail_descr('''i3, %s, i3 + self.check_expanded_fail_descr('''i3, i3, %s where p1 is a node_vtable, valuedescr=i2, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2''' % arg, rop.GUARD_TRUE) @@ -2242,7 +2262,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p1, descr=nextdescr) # a cycle - guard_true(i1, descr=fdescr) [p1, i3, p2, i4] + guard_true(i1, descr=fdescr) [i3, i4, p1, p2] jump(i2, i1, i3, i4) """ expected = """ @@ -2251,7 +2271,7 @@ jump(i2, 1, i3, i4) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3, p2, i4 + self.check_expanded_fail_descr('''i3, i4, p1, p2 where p1 is a node_vtable, valuedescr=i4, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p1 ''', rop.GUARD_TRUE) @@ -2626,7 +2646,7 @@ setfield_gc(p2, 5, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p1) """ # XXX we should optimize a bit more the case of a nonvirtual. @@ -2668,7 +2688,7 @@ setfield_gc(p1b, 252, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ self.optimize_loop(ops, 'Not, Not', expected) @@ -2709,7 +2729,7 @@ setfield_gc(p1b, i1, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ # the point of this test is that 'i1' should show up in the fail_args @@ -2780,7 +2800,7 @@ escape(p2) p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [] jump(i1) @@ -2806,7 +2826,7 @@ setfield_gc(p2, 23, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [i1] jump(i1, p1) @@ -2880,31 +2900,31 @@ ''' self.optimize_loop(ops, 'Not', expected) -class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): +##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): - def test_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - expected = """ - [i0] - jump(1) - """ - self.optimize_loop(ops, 'Not', expected) +## def test_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## expected = """ +## [i0] +## jump(1) +## """ +## self.optimize_loop(ops, 'Not', expected) - def test_instanceof_guard_class(self): - ops = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - i1 = instanceof(p0, descr=nodesize) - jump(i1, p0) - """ - expected = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - jump(1, p0) - """ - self.optimize_loop(ops, 'Not, Not', expected) +## def test_instanceof_guard_class(self): +## ops = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## i1 = instanceof(p0, descr=nodesize) +## jump(i1, p0) +## """ +## expected = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## jump(1, p0) +## """ +## self.optimize_loop(ops, 'Not, Not', expected) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_pyjitpl.py Tue Jun 8 19:48:40 2010 @@ -1,49 +1,20 @@ # some unit tests for the bytecode decoding -from pypy.jit.metainterp import pyjitpl, codewriter, resoperation, history +from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp import jitprof -from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.history import History from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.test.test_optimizeopt import equaloplists +from pypy.jit.codewriter.jitcode import JitCode -def make_frame(code): - bytecode = codewriter.JitCode("hello") - bytecode.code = code - bytecode.constants = None - frame = pyjitpl.MIFrame(None, bytecode) - frame.pc = 0 - return frame - - -def test_decode_big_int(): - for code, value in [("\x80\x01", 128), ("\x81\x81\x01", 1 + (1 << 7) + (1 << 14))]: - frame = make_frame(code) - val = frame.load_int() - assert val == value - -def test_decode_bool(): - frame = make_frame("\x00") - assert not frame.load_bool() - - frame = make_frame("\x01") - assert frame.load_bool() - -def test_simple_opimpl_exist(): - rop = resoperation.rop - for opnum, opname in resoperation.opname.items(): - if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE, - rop.FORCE_TOKEN): - continue - if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST: - assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname def test_portal_trace_positions(): - jitcode = codewriter.JitCode("f") - jitcode.code = jitcode.constants = None - portal = codewriter.JitCode("portal") - portal.code = portal.constants = None + jitcode = JitCode("f") + jitcode.setup(None) + portal = JitCode("portal") + portal.setup(None) class FakeStaticData: cpu = None portal_code = portal @@ -95,7 +66,7 @@ c3 = ConstInt(3) boxes = [b1, b2, b1, c3] dup = {} - metainterp.remove_consts_and_duplicates(boxes, 0, 4, dup) + metainterp.remove_consts_and_duplicates(boxes, 4, dup) assert boxes[0] is b1 assert boxes[1] is b2 assert is_another_box_like(boxes[2], b1) @@ -108,12 +79,12 @@ # del metainterp.history.operations[:] b4 = BoxInt(4) - boxes = ["something random", b2, b4, "something else"] - metainterp.remove_consts_and_duplicates(boxes, 1, 3, dup) - assert is_another_box_like(boxes[1], b2) - assert boxes[2] is b4 + boxes = [b2, b4, "something random"] + metainterp.remove_consts_and_duplicates(boxes, 2, dup) + assert is_another_box_like(boxes[0], b2) + assert boxes[1] is b4 assert equaloplists(metainterp.history.operations, [ - ResOperation(rop.SAME_AS, [b2], boxes[1]), + ResOperation(rop.SAME_AS, [b2], boxes[0]), ]) def test_get_name_from_address(): @@ -121,42 +92,7 @@ def __init__(self): pass metainterp_sd = FakeMetaInterpSd() - metainterp_sd.info_from_codewriter(None, None, - [(123, "a"), (456, "b")], - None) + metainterp_sd.setup_list_of_addr2name([(123, 'a'), (456, 'b')]) assert metainterp_sd.get_name_from_address(123) == 'a' assert metainterp_sd.get_name_from_address(456) == 'b' assert metainterp_sd.get_name_from_address(789) == '' - -def test_initialize_state_from_guard_failure(): - from pypy.jit.metainterp.typesystem import llhelper - calls = [] - - class FakeCPU: - ts = llhelper - - def make_boxes_from_latest_values(self, faildescr): - return [BoxInt(0), None, BoxInt(2), None, BoxInt(4)] - - class FakeStaticData: - cpu = FakeCPU() - profiler = jitprof.EmptyProfiler() - - metainterp = pyjitpl.MetaInterp(FakeStaticData()) - - def rebuild_state_after_failure(descr, newboxes): - calls.append(newboxes) - metainterp.rebuild_state_after_failure = rebuild_state_after_failure - - class FakeResumeDescr: - def must_compile(self, *args): - return True - resumedescr = FakeResumeDescr() - metainterp.initialize_state_from_guard_failure(resumedescr) - - inp = metainterp.history.inputargs - assert len(inp) == 3 - assert [box.value for box in inp] == [0, 2, 4] - b0, b2, b4 = inp - assert len(calls) == 1 - assert calls[0] == [b0, None, b2, None, b4] Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_recursive.py Tue Jun 8 19:48:40 2010 @@ -1,7 +1,8 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint +from pypy.rlib.jit import unroll_safe from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats @@ -24,6 +25,7 @@ return 1 res = self.meta_interp(main, [20], optimizer=OPTIMIZER_SIMPLE) assert res == main(20) + self.check_history(call=0) def test_simple_recursion_with_exc(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm']) @@ -105,11 +107,11 @@ def can_inline(*args): return True else: - def can_inline(code, i): + def can_inline(i, code): code = hlstr(code) return not JUMP_BACK in code - jitdriver = JitDriver(greens = ['code', 'i'], reds = ['n'], + jitdriver = JitDriver(greens = ['i', 'code'], reds = ['n'], can_inline = can_inline) def interpret(codenum, n, i): @@ -178,12 +180,12 @@ def test_guard_failure_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -215,12 +217,12 @@ def test_guard_failure_and_then_exception_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n', 'flag'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n', 'flag'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -259,12 +261,12 @@ def test_exception_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) class Exc(Exception): @@ -305,12 +307,12 @@ # it fails, it is very delicate in terms of parameters, # bridge/loop creation order from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -394,9 +396,36 @@ self.check_aborted_count(8) self.check_enter_count_at_most(30) + def test_trace_limit_with_exception_bug(self): + myjitdriver = JitDriver(greens=[], reds=['n']) + @unroll_safe + def do_stuff(n): + while n > 0: + n -= 1 + raise ValueError + def loop(n): + pc = 0 + while n > 80: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + try: + do_stuff(n) + except ValueError: + # the trace limit is checked when we arrive here, and we + # have the exception still in last_exc_value_box at this + # point -- so when we abort because of a trace too long, + # the exception is passed to the blackhole interp and + # incorrectly re-raised from here + pass + n -= 1 + return n + TRACE_LIMIT = 66 + res = self.meta_interp(loop, [100], trace_limit=TRACE_LIMIT) + assert res == 80 + def test_max_failure_args(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -429,7 +458,7 @@ def test_max_failure_args_exc(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -495,12 +524,12 @@ self.check_loops(call_may_force=0, call=0) def test_trace_from_start(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -535,12 +564,12 @@ self.check_history(int_add=1) def test_dont_inline_huge_stuff(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -693,7 +722,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -729,7 +758,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -770,7 +799,7 @@ assert res == main(0) def test_directly_call_assembler_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'x', 'frame'], virtualizables = ['frame'], can_inline = lambda codeno : False) @@ -816,7 +845,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_resume.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_resume.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_resume.py Tue Jun 8 19:48:40 2010 @@ -3,10 +3,11 @@ from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue from pypy.jit.metainterp.optimizeopt import VStructValue from pypy.jit.metainterp.resume import * -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, ConstAddr +from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.history import ConstPtr, ConstFloat from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin from pypy.jit.metainterp import executor +from pypy.jit.codewriter import heaptracker class Storage: rd_frame_info_list = None @@ -60,12 +61,12 @@ self.resboxes = [] def newframe(self, jitcode): - frame = FakeFrame(jitcode, -1, -1) + frame = FakeFrame(jitcode, -1) self.framestack.append(frame) return frame def execute_and_record(self, opnum, descr, *argboxes): - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) + resbox = executor.execute(self.cpu, None, opnum, descr, *argboxes) self.trace.append((opnum, list(argboxes), resbox, @@ -74,10 +75,75 @@ self.resboxes.append(resbox) return resbox +S = lltype.GcStruct('S') +gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcrefnull = lltype.nullptr(llmemory.GCREF.TO) + +class MyCPU: + class ts: + NULLREF = gcrefnull + CONST_NULL = ConstPtr(gcrefnull) + def __init__(self, values): + self.values = values + def get_latest_value_count(self): + return len(self.values) + def get_latest_value_int(self, index): + return self.values[index] + def get_latest_value_ref(self, index): + return self.values[index] + def get_latest_value_float(self, index): + return self.values[index] + +class MyBlackholeInterp: + def __init__(self, ARGS): + self.written_i = [] + self.written_r = [] + self.written_f = [] + self.ARGS = ARGS + + def get_current_position_info(self): + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + count_i = count_r = count_f = 0 + for index, ARG in enumerate(self.ARGS): + if ARG == lltype.Signed: + callback_i(index, count_i); count_i += 1 + elif ARG == llmemory.GCREF: + callback_r(index, count_r); count_r += 1 + elif ARG == lltype.Float: + callback_f(index, count_f); count_f += 1 + else: + assert 0 + return MyInfo() + + def setarg_i(self, index, value): + assert index == len(self.written_i) + self.written_i.append(value) + + def setarg_r(self, index, value): + assert index == len(self.written_r) + self.written_r.append(value) + + def setarg_f(self, index, value): + assert index == len(self.written_f) + self.written_f.append(value) + +def _next_section(reader, *expected): + bh = MyBlackholeInterp(map(lltype.typeOf, expected)) + reader.consume_one_section(bh) + expected_i = [x for x in expected if lltype.typeOf(x) == lltype.Signed] + expected_r = [x for x in expected if lltype.typeOf(x) == llmemory.GCREF] + expected_f = [x for x in expected if lltype.typeOf(x) == lltype.Float] + assert bh.written_i == expected_i + assert bh.written_r == expected_r + assert bh.written_f == expected_f + def test_simple_read(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] - c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] + #b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] + c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)] storage = Storage() storage.rd_consts = [c1, c2, c3] numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) @@ -88,44 +154,54 @@ tag(0, TAGBOX), tag(1, TAGBOX)]) storage.rd_numb = numb - - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), LLtypeMixin.cpu.ts.CONST_NULL, b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([42, gcref1, -66]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 42, 111, gcrefnull, 42, gcref1) + _next_section(reader, 222, 333) + _next_section(reader, 42, gcref1, -66) + # + metainterp = MyMetaInterp(cpu) + reader = ResumeDataBoxReader(storage, metainterp) + bi, br, bf = [None]*3, [None]*2, [None]*0 + info = MyBlackholeInterp([lltype.Signed, lltype.Signed, + llmemory.GCREF, lltype.Signed, + llmemory.GCREF]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b1s = reader.liveboxes[0] + b2s = reader.liveboxes[1] + assert bi == [b1s, ConstInt(111), b1s] + assert br == [ConstPtr(gcrefnull), b2s] + bi, br, bf = [None]*2, [None]*0, [None]*0 + info = MyBlackholeInterp([lltype.Signed, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + assert bi == [ConstInt(222), ConstInt(333)] + bi, br, bf = [None]*2, [None]*1, [None]*0 + info = MyBlackholeInterp([lltype.Signed, llmemory.GCREF, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b3s = reader.liveboxes[2] + assert bi == [b1s, b3s] + assert br == [b2s] + # def test_simple_read_tagged_ints(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] storage = Storage() storage.rd_consts = [] - numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) - numb = Numbering(numb, [tag(2, TAGINT), tag(3, TAGINT)]) - numb = Numbering(numb, [tag(0, TAGBOX), - tag(1, TAGINT), - tag(0, TAGBOX), - tag(1, TAGBOX)]) + numb = Numbering(None, [tag(100, TAGINT)]) storage.rd_numb = numb - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 100) def test_prepare_virtuals(): class FakeVinfo(object): - def allocate(self, metainterp): + def allocate(self, decoder): return "allocated" - def setfields(self, metainterp, virtual, func): + def setfields(self, decoder, virtual): assert virtual == "allocated" class FakeStorage(object): rd_virtuals = [FakeVinfo(), None] @@ -135,8 +211,8 @@ class FakeMetainterp(object): _already_allocated_resume_virtuals = None cpu = None - reader = ResumeDataReader(FakeStorage(), [], FakeMetainterp()) - assert reader.virtuals == ["allocated", None] + reader = ResumeDataDirectReader(None, FakeStorage()) + assert reader.virtuals == ["allocated", reader.virtual_default] # ____________________________________________________________ @@ -146,11 +222,13 @@ parent_resumedata_snapshot = None parent_resumedata_frame_info_list = None - def __init__(self, code, pc, exc_target, *boxes): + def __init__(self, code, pc, *boxes): self.jitcode = code self.pc = pc - self.exception_target = exc_target - self.env = list(boxes) + self._env = list(boxes) + + def get_list_of_active_boxes(self, flag): + return self._env def setup_resume_at_op(self, pc, exception_target, env): self.__init__(self.jitcode, pc, exception_target, *env) @@ -160,8 +238,7 @@ def __ne__(self, other): return self.__dict__ != other.__dict__ def __repr__(self): - return "" % (self.jitcode, self.pc, - self.exception_target, self.env) + return "" % (self.jitcode, self.pc, self._env) def test_Snapshot_create(): l = ['b0', 'b1'] @@ -176,20 +253,16 @@ def test_FrameInfo_create(): jitcode = "JITCODE" - frame = FakeFrame(jitcode, 1, 2) - fi = FrameInfo(None, frame) + fi = FrameInfo(None, jitcode, 1) assert fi.prev is None assert fi.jitcode is jitcode assert fi.pc == 1 - assert fi.exception_target == 2 jitcode1 = "JITCODE1" - frame1 = FakeFrame(jitcode, 3, 4) - fi1 = FrameInfo(fi, frame1) + fi1 = FrameInfo(fi, jitcode1, 3) assert fi1.prev is fi - assert fi1.jitcode is jitcode + assert fi1.jitcode is jitcode1 assert fi1.pc == 3 - assert fi1.exception_target == 4 def test_Numbering_create(): l = [1, 2] @@ -205,7 +278,7 @@ def test_capture_resumedata(): b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] - fs = [FakeFrame("code0", 0, -1, b1, c1, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2)] storage = Storage() capture_resumedata(fs, None, [], storage) @@ -218,13 +291,12 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) frame_info_list = storage.rd_frame_info_list @@ -235,26 +307,23 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env - assert snapshot.boxes is not fs[2].env + assert snapshot.boxes == fs[2]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is fs[1].parent_resumedata_frame_info_list assert frame_info_list.jitcode == 'code1' snapshot = snapshot.prev assert snapshot.prev is fs[1].parent_resumedata_snapshot - assert snapshot.boxes == fs[1].env - assert snapshot.boxes is not fs[1].env + assert snapshot.boxes == fs[1]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is None assert frame_info_list.jitcode == 'code0' snapshot = snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env - fs[2].env = [b2, b3] + fs[2]._env = [b3, b2] fs[2].pc = 15 vbs = [b1, b2] vrs = [b3] @@ -266,16 +335,11 @@ assert frame_info_list.pc == 15 snapshot = storage.rd_snapshot - assert snapshot.boxes == vbs - assert snapshot.boxes is not vbs - - snapshot = snapshot.prev - assert snapshot.boxes == vrs - assert snapshot.boxes is not vrs + assert snapshot.boxes == vrs + vbs # in the same list snapshot = snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env + assert snapshot.boxes == fs[2]._env class FakeMetaInterpStaticData: @@ -285,12 +349,13 @@ failargs_limit = 100 def test_rebuild_from_resumedata(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -300,21 +365,21 @@ b1t, b2t, b3t = [BoxInt(), BoxPtr(), BoxInt()] newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t) - result = rebuild_from_resumedata(metainterp, newboxes, storage, - False) + result = rebuild_from_resumedata(metainterp, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_with_virtualizable(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxPtr()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, [b4], [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -327,21 +392,22 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, True) assert result == ([b4t], []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -359,9 +425,9 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b2, b3, b4], b1t, b2t, b3t, b4t) @@ -370,7 +436,7 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage2, False) assert result == (None, []) - fs2 = fs2[:-1] + [FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = fs2[:-1] + [FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 @@ -379,6 +445,9 @@ pass fakeoptimizer = FakeOptimizer_VirtualValue() +def ConstAddr(addr, cpu): # compatibility + return ConstInt(heaptracker.adr2int(addr)) + def virtual_value(keybox, value, next): vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu), keybox) @@ -389,17 +458,18 @@ return vv def test_rebuild_from_resumedata_two_guards_w_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -433,9 +503,9 @@ False) b2t = metainterp.resboxes[0] - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b3, b4], b1t, b3t, b4t) @@ -445,17 +515,18 @@ False) b2t = metainterp.resboxes[0] assert len(metainterp.resboxes) == 2 - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards_w_shared_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5, b6 = [BoxPtr(), BoxPtr(), BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, c1, b2, b3)] + fs = [FakeFrame("code0", 0, c1, b2, b3)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -467,7 +538,7 @@ tag(0, TAGCONST)] storage2 = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b4, b2)] + fs = [FakeFrame("code0", 0, b1, b4, b2)] capture_resumedata(fs, None, [], storage2) values[b4] = virtual_value(b4, b6, c4) modifier = ResumeDataVirtualAdder(storage2, memo) @@ -478,9 +549,10 @@ def test_resumedata_top_recursive_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxPtr(), BoxPtr(), BoxInt()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b2)] + fs = [FakeFrame("code0", 0, b1, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -727,16 +799,11 @@ modifier = ResumeDataVirtualAdder(storage, memo) liveboxes = modifier.finish({}) assert storage.rd_snapshot is None - metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, [], metainterp) - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [ConstInt(sys.maxint), ConstInt(1), ConstInt(sys.maxint), - ConstInt(2**16)] - assert metainterp.trace == [] + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, sys.maxint, 2**16, -65) + _next_section(reader, 2, 3) + _next_section(reader, sys.maxint, 1, sys.maxint, 2**16) def test_virtual_adder_memo_const_sharing(): @@ -756,6 +823,46 @@ assert storage2.rd_consts is memo.consts +class ResumeDataFakeReader(ResumeDataBoxReader): + """Another subclass of AbstractResumeDataReader meant for tests.""" + def __init__(self, storage, newboxes, metainterp): + self._init(metainterp.cpu, storage) + self.liveboxes = newboxes + self.metainterp = metainterp + self._prepare(storage) + + def consume_boxes(self): + self.lst = [] + class Whatever: + def __eq__(self, other): + return True + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + for index, tagged in enumerate(self.cur_numb.nums): + box = self.decode_box(tagged, Whatever()) + if box.type == INT: + callback_i(index, index) + elif box.type == REF: + callback_r(index, index) + elif box.type == FLOAT: + callback_f(index, index) + else: + assert 0 + self._prepare_next_section(MyInfo()) + return self.lst + + def write_an_int(self, count_i, box): + assert box.type == INT + self.lst.append(box) + def write_a_ref(self, count_r, box): + assert box.type == REF + self.lst.append(box) + def write_a_float(self, count_f, box): + assert box.type == FLOAT + self.lst.append(box) + + def test_virtual_adder_no_op_renaming(): b1s, b2s, b3s = [BoxInt(1), BoxInt(2), BoxInt(3)] storage = make_storage(b1s, b2s, b3s) @@ -777,7 +884,7 @@ b1t, b3t = [BoxInt(11), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b1_2, b3s], b1t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() assert lst == [b1t, b1t, b3t] lst = reader.consume_boxes() @@ -797,7 +904,7 @@ b2t, b3t = [BoxPtr(demo55o), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() c1t = ConstInt(111) assert lst == [c1t, b2t, b3t] @@ -849,10 +956,10 @@ b5s], b3t, b5t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 2 - b2t = reader._decode_box(modifier._gettagged(b2s)) - b4t = reader._decode_box(modifier._gettagged(b4s)) + b2t = reader.decode_ref(modifier._gettagged(b2s)) + b4t = reader.decode_ref(modifier._gettagged(b4s)) trace = metainterp.trace b2new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu)], @@ -912,9 +1019,9 @@ b4t) # resume metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ (rop.NEW_ARRAY, [ConstInt(2)], b2t, LLtypeMixin.arraydescr), @@ -957,9 +1064,9 @@ # NULL = ConstPtr.value metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ @@ -1004,7 +1111,7 @@ newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert reader.virtuals is None trace = metainterp.trace b2set = (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_send.py Tue Jun 8 19:48:40 2010 @@ -1,7 +1,6 @@ import py from pypy.rlib.jit import JitDriver, hint, purefunction -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -375,7 +374,7 @@ self.check_loop_count(2) def test_behavior_change_after_a_while(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x']) class Base: def __init__(self, value): self.value = value @@ -455,7 +454,7 @@ self.check_tree_loop_count(2) def test_bug1(self): - myjitdriver = JitDriver(greens = [], reds = ['node', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) class Base: pass class A(Base): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_slist.py Tue Jun 8 19:48:40 2010 @@ -1,5 +1,4 @@ import py -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE @@ -65,7 +64,7 @@ assert res == 0 def test_getitem(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'lst', 'i']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'lst']) def f(n): lst = [] for i in range(n): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_string.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_string.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_string.py Tue Jun 8 19:48:40 2010 @@ -1,13 +1,13 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class StringTests: def test_eq_residual(self): - jitdriver = JitDriver(greens = [], reds = ['s', 'n', 'i']) + jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's']) global_s = "hello" def f(n, b, s): if b: @@ -44,6 +44,34 @@ assert res == 5 self.check_loops(**{self.CALL_PURE: 0}) + def test_newstr(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = 'adlfkj' + chr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + + def test_newunicode(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = u'adlfkj' + unichr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + class TestOOtype(StringTests, OOJitMixin): CALL_PURE = "oosend_pure" Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tl.py Tue Jun 8 19:48:40 2010 @@ -1,6 +1,6 @@ import py -from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import OPTIMIZER_SIMPLE +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_tlc.py Tue Jun 8 19:48:40 2010 @@ -21,7 +21,7 @@ pool = tlc.ConstantPool() bytecode = tlc.compile(src, pool) interp = self._get_interp(bytecode, pool) - return self.meta_interp(interp, [0, inputarg], view=False) + return self.meta_interp(interp, [0, inputarg]) def test_method(self): code = """ Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtual.py Tue Jun 8 19:48:40 2010 @@ -1,12 +1,12 @@ import py from pypy.rlib.jit import JitDriver, hint from pypy.rlib.objectmodel import compute_unique_id -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.ootypesystem import ootype -from pypy.jit.metainterp import heaptracker +from pypy.jit.codewriter import heaptracker class VirtualTests: def _freeze_(self): @@ -299,10 +299,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) class VirtualMiscTests: Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualizable.py Tue Jun 8 19:48:40 2010 @@ -2,14 +2,15 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy +from pypy.jit.codewriter import heaptracker from pypy.rlib.jit import JitDriver, hint, dont_look_inside from pypy.rlib.jit import OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.rarithmetic import intmask from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.rclass import FieldListAccessor from pypy.jit.metainterp.warmspot import get_stats, get_translator -from pypy.jit.metainterp import history, heaptracker +from pypy.jit.metainterp import history from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin def promote_virtualizable(*args): @@ -461,7 +462,7 @@ def test_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -521,7 +522,7 @@ def test_external_pass(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 'z'], + jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'], virtualizables = ['frame']) class BaseFrame(object): @@ -583,6 +584,45 @@ self.check_aborted_count(2) self.check_tree_loop_count(0) + def test_external_read_with_exception(self): + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = ['x', 'y'] + class SomewhereElse: + pass + somewhere_else = SomewhereElse() + + class FooError(Exception): + def __init__(self, value): + self.value = value + + def g(): + result = somewhere_else.top_frame.y # external read + debug_print(lltype.Void, '-+-+-+-+- external read:', result) + raise FooError(result) + + def f(n): + frame = Frame() + frame.x = n + frame.y = 10 + somewhere_else.top_frame = frame + while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) + try: + g() + except FooError, e: + frame.x -= e.value + frame.y += 1 + return frame.x + + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) + assert res == f(123) + self.check_aborted_count(2) + self.check_tree_loop_count(0) + def test_external_write(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -821,7 +861,7 @@ assert res == f(123) def test_external_read_sometimes_recursive(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'rec'], + jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -941,7 +981,7 @@ assert res == f(123) def test_promote_index_in_virtualizable_list(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1084,7 +1124,7 @@ res = self.meta_interp(f, [10]) assert res == 55 - self.check_loops(new_with_vtable=0, oois=1) + self.check_loops(new_with_vtable=0, ptr_eq=1) def test_virtual_child_frame_with_arrays(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], @@ -1196,7 +1236,7 @@ if not self.basic: py.test.skip("purely frontend test") - myjitdriver = JitDriver(greens = [], reds = ['frame', 'fail'], + myjitdriver = JitDriver(greens = [], reds = ['fail', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -1251,7 +1291,7 @@ self.x = x self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) def interp(caller): @@ -1284,15 +1324,15 @@ self.n = n self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['frame'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['frame'], virtualizables=["frame"], get_printable_location=p, can_inline=c) def f(code, frame): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualref.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualref.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_virtualref.py Tue Jun 8 19:48:40 2010 @@ -12,9 +12,9 @@ class VRefTests: - def finish_metainterp_for_interp_operations(self, metainterp): - self.vrefinfo = VirtualRefInfo(metainterp.staticdata.state) - metainterp.staticdata.virtualref_info = self.vrefinfo + def finish_setup_for_interp_operations(self): + self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) + self.cw.setup_vrefinfo(self.vrefinfo) def test_make_vref_simple(self): class X: @@ -81,8 +81,26 @@ JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # - self.metainterp.rebuild_state_after_failure(guard_op.descr, - guard_op.fail_args[:]) + # try reloading from blackhole.py's point of view + from pypy.jit.metainterp.resume import ResumeDataDirectReader + cpu = self.metainterp.cpu + cpu.get_latest_value_count = lambda : len(guard_op.fail_args) + cpu.get_latest_value_int = lambda i:guard_op.fail_args[i].getint() + cpu.get_latest_value_ref = lambda i:guard_op.fail_args[i].getref_base() + cpu.clear_latest_values = lambda count: None + resumereader = ResumeDataDirectReader(cpu, guard_op.descr) + vrefinfo = self.metainterp.staticdata.virtualref_info + lst = [] + vrefinfo.continue_tracing = lambda vref, virtual: \ + lst.append((vref, virtual)) + resumereader.consume_vref_and_vable(vrefinfo, None) + del vrefinfo.continue_tracing + assert len(lst) == 1 + lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), + lst[0][0]) # assert correct type + # + # try reloading from pyjitpl's point of view + self.metainterp.rebuild_state_after_failure(guard_op.descr) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value @@ -424,7 +442,7 @@ self.check_aborted_count(0) def test_recursive_call_1(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: pass @@ -454,7 +472,7 @@ self.check_aborted_count(0) def test_recursive_call_2(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: n = 0 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmspot.py Tue Jun 8 19:48:40 2010 @@ -277,13 +277,13 @@ type_system = 'lltype' class TestOOWarmspot(WarmspotTests, OOJitMixin): - CPUClass = runner.OOtypeCPU + ##CPUClass = runner.OOtypeCPU type_system = 'ootype' class TestWarmspotDirect(object): def setup_class(cls): from pypy.jit.metainterp.typesystem import llhelper - from pypy.jit.metainterp.support import annotate + from pypy.jit.codewriter.support import annotate from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.rpython.lltypesystem import lltype, llmemory @@ -299,7 +299,7 @@ raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally( - [BoxInt(0), BoxInt(1)]) + [0], [], [], [1], [], []) if self.no == 3: exc = lltype.malloc(OBJECT) exc.typeptr = exc_vtable @@ -308,10 +308,15 @@ lltype.cast_opaque_ptr(llmemory.GCREF, exc)) return self.no + class FakeDescr: + def as_vtable_size_descr(self): + return self + class FakeCPU(object): supports_floats = False ts = llhelper translate_support_code = False + stats = "stats" def get_fail_descr_number(self, d): return -1 @@ -320,7 +325,7 @@ pass def nodescr(self, *args, **kwds): - pass + return FakeDescr() fielddescrof = nodescr calldescrof = nodescr sizeof = nodescr @@ -343,6 +348,7 @@ return red rtyper = annotate(f, [0]) + FakeCPU.rtyper = rtyper translator = rtyper.annotator.translator translator.config.translation.gc = 'hybrid' cls.desc = WarmRunnerDesc(translator, CPUClass=FakeCPU) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_warmstate.py Tue Jun 8 19:48:40 2010 @@ -128,8 +128,7 @@ class FakeWarmRunnerDesc: cpu = FakeCPU() red_args_types = ["int", "float"] - class metainterp_sd: - virtualizable_info = None + virtualizable_info = None # state = WarmEnterState(FakeWarmRunnerDesc()) set_future_values = state.make_set_future_values() Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_ztranslation.py Tue Jun 8 19:48:40 2010 @@ -5,7 +5,6 @@ from pypy.rlib.jit import PARAMETERS, dont_look_inside from pypy.jit.metainterp.jitprof import Profiler from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.ootypesystem import ootype class TranslationTest: @@ -40,7 +39,7 @@ def can_inline(): return False - jitdriver = JitDriver(greens = [], reds = ['frame', 'total'], + jitdriver = JitDriver(greens = [], reds = ['total', 'frame'], virtualizables = ['frame'], get_jitcell_at=get_jitcell_at, set_jitcell_at=set_jitcell_at, Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/typesystem.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/typesystem.py Tue Jun 8 19:48:40 2010 @@ -4,6 +4,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import r_dict def deref(T): @@ -44,9 +45,9 @@ BASETYPE = llmemory.GCREF BoxRef = history.BoxPtr ConstRef = history.ConstPtr - ConstAddr = history.ConstAddr loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstPtr(history.ConstPtr.value) + NULLREF = history.ConstPtr.value + CONST_NULL = history.ConstPtr(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -71,17 +72,16 @@ def cast_fnptr_to_root(self, fnptr): return llmemory.cast_ptr_to_adr(fnptr) - def cls_of_box(self, cpu, box): + def cls_of_box(self, box): obj = box.getref(lltype.Ptr(rclass.OBJECT)) cls = llmemory.cast_ptr_to_adr(obj.typeptr) - return history.ConstInt(cpu.cast_adr_to_int(cls)) + return history.ConstInt(heaptracker.adr2int(cls)) - def subclassOf(self, cpu, clsbox1, clsbox2): - adr = clsbox2.getaddr(cpu) + def instanceOf(self, instbox, clsbox): + adr = clsbox.getaddr() bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - adr = clsbox1.getaddr(cpu) - real_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - return rclass.ll_issubclass(real_class, bounding_class) + real_instance = instbox.getref(rclass.OBJECTPTR) + return rclass.ll_isinstance(real_instance, bounding_class) def get_exception_box(self, etype): return history.ConstInt(etype) @@ -120,7 +120,7 @@ def cast_vtable_to_hashable(self, cpu, ptr): adr = llmemory.cast_ptr_to_adr(ptr) - return cpu.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) def cast_from_ref(self, TYPE, value): return lltype.cast_opaque_ptr(TYPE, value) @@ -130,8 +130,8 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): - return box.getaddr(cpu) + def getaddr_for_box(self, box): + return box.getaddr() def rd_eq(ref1, ref2): return ref1 == ref2 @@ -151,9 +151,9 @@ BASETYPE = ootype.Object BoxRef = history.BoxObj ConstRef = history.ConstObj - ConstAddr = history.ConstObj loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstObj(history.ConstObj.value) + NULLREF = history.ConstObj.value + CONST_NULL = history.ConstObj(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -233,7 +233,7 @@ return ootype.cast_to_object(value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): + def getaddr_for_box(self, box): return box.getref_base() llhelper = LLTypeHelper() Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualizable.py Tue Jun 8 19:48:40 2010 @@ -72,6 +72,10 @@ for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] + self.static_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)]) + self.array_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.array_field_descrs)]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem @@ -102,6 +106,52 @@ i = i + 1 assert len(boxes) == i + 1 # + def write_from_resume_data_partial(virtualizable, reader, nums): + # Load values from the reader (see resume.py) described by + # the list of numbers 'nums', and write them in their proper + # place in the 'virtualizable'. This works from the end of + # the list and returns the index in 'nums' of the start of + # the virtualizable data found, allowing the caller to do + # further processing with the start of the list. + i = len(nums) - 1 + assert i >= 0 + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i]) + setarrayitem(lst, j, x) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(FIELDTYPE, nums[i]) + setattr(virtualizable, fieldname, x) + return i + # + def load_list_of_boxes(virtualizable, reader, nums): + # Uses 'virtualizable' only to know the length of the arrays; + # does not write anything into it. The returned list is in + # the format expected of virtualizable_boxes, so it ends in + # the virtualizable itself. + i = len(nums) - 1 + assert i >= 0 + boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])] + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i]) + boxes.append(box) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(FIELDTYPE, nums[i]) + boxes.append(box) + boxes.reverse() + return boxes + # def check_boxes(virtualizable, boxes): # for debugging i = 0 @@ -141,8 +191,14 @@ static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) + unroll_static_fields_rev = unrolling_iterable( + reversed(list(unroll_static_fields))) + unroll_array_fields_rev = unrolling_iterable( + reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes + self.write_from_resume_data_partial = write_from_resume_data_partial + self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length @@ -172,6 +228,9 @@ return self.cpu.ts.cast_to_instance_maybe(self.VTYPEPTR, virtualizable) cast_to_vtype._annspecialcase_ = 'specialize:ll' + def cast_gcref_to_vtype(self, virtualizable): + return lltype.cast_opaque_ptr(self.VTYPEPTR, virtualizable) + def is_vtypeptr(self, TYPE): return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR) @@ -212,12 +271,6 @@ assert virtualizable.vable_token == self.TOKEN_NONE force_now._dont_inline_ = True - def forced_vable(self, virtualizable_boxes): - virtualizable_box = virtualizable_boxes[-1] - virtualizable = self.unwrap_virtualizable_box(virtualizable_box) - self.write_boxes(virtualizable, virtualizable_boxes) - virtualizable.vable_token = self.TOKEN_NONE - # ____________________________________________________________ # # The 'vable_token' field of a virtualizable is either 0, -1, or points Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualref.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualref.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/virtualref.py Tue Jun 8 19:48:40 2010 @@ -1,6 +1,7 @@ from pypy.rpython.rmodel import inputconst, log from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker class VirtualRefInfo: @@ -20,7 +21,8 @@ 'jit_virtual_ref') # build some constants adr = llmemory.cast_ptr_to_adr(self.jit_virtual_ref_vtable) - self.jit_virtual_ref_const_class = history.ConstAddr(adr, self.cpu) + adr = heaptracker.adr2int(adr) + self.jit_virtual_ref_const_class = history.ConstInt(adr) fielddescrof = self.cpu.fielddescrof self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF, 'virtual_token') @@ -60,11 +62,11 @@ # The 'virtual_token' field has the same meaning as the 'vable_token' field # of a virtualizable. It is equal to: - # * -2 (TOKEN_NONE) when tracing, except as described below; + # * -3 (TOKEN_NONE) when tracing, except as described below; # * -1 (TOKEN_TRACING_RESCALL) during tracing when we do a residual call; # * addr in the CPU stack (set by FORCE_TOKEN) when running the assembler; - # * -2 (TOKEN_NONE) after the virtual is forced, if it is forced at all. - TOKEN_NONE = -2 + # * -3 (TOKEN_NONE) after the virtual is forced, if it is forced at all. + TOKEN_NONE = -3 TOKEN_TRACING_RESCALL = -1 def virtual_ref_during_tracing(self, real_object): @@ -104,16 +106,6 @@ # marker "modified during residual call" set. return True - def forced_single_vref(self, gcref, real_object): - if not self.is_virtual_ref(gcref): - return - assert real_object - vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) - assert (vref.virtual_token != self.TOKEN_NONE and - vref.virtual_token != self.TOKEN_TRACING_RESCALL) - vref.virtual_token = self.TOKEN_NONE - vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) - def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmspot.py Tue Jun 8 19:48:40 2010 @@ -16,12 +16,13 @@ from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.unsimplify import call_final_function -from pypy.jit.metainterp import codewriter -from pypy.jit.metainterp import support, history, pyjitpl, gc +from pypy.jit.metainterp import history, pyjitpl, gc from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp -from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler +from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.codewriter import support, codewriter +from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE # ____________________________________________________________ @@ -130,9 +131,6 @@ stats.maybe_view() stats.check_consistency() -class JitException(Exception): - _go_through_llinterp_uncaught_ = True # ugh - class ContinueRunningNormallyBase(JitException): pass @@ -144,47 +142,49 @@ class WarmRunnerDesc(object): def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, - optimizer=None, **kwds): + optimizer=None, ProfilerClass=EmptyProfiler, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! - if policy is None: - policy = JitPolicy() self.set_translator(translator) + self.build_cpu(CPUClass, **kwds) self.find_portal() - self.codewriter = codewriter.CodeWriter(self.rtyper) - graphs = self.codewriter.find_all_graphs(self.portal_graph, - policy, - CPUClass.supports_floats) + self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + if policy is None: + policy = JitPolicy() + policy.set_supports_floats(self.cpu.supports_floats) + graphs = self.codewriter.find_all_graphs(policy) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) - self.build_meta_interp(CPUClass, **kwds) + self.build_meta_interp(ProfilerClass) self.make_args_specification() # from pypy.jit.metainterp.virtualref import VirtualRefInfo - self.metainterp_sd.virtualref_info = VirtualRefInfo(self) + vrefinfo = VirtualRefInfo(self) + self.codewriter.setup_vrefinfo(vrefinfo) if self.jitdriver.virtualizables: from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.metainterp_sd.virtualizable_info = VirtualizableInfo(self) + self.virtualizable_info = VirtualizableInfo(self) + self.codewriter.setup_virtualizable_info(self.virtualizable_info) + else: + self.virtualizable_info = None # self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_function() self.rewrite_jit_merge_point(policy) - - self.codewriter.generate_bytecode(self.metainterp_sd, - self.portal_graph, - self.portal_runner_ptr - ) + + verbose = not self.cpu.translate_support_code + self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jit() self.rewrite_set_param() - self.rewrite_force_virtual() + self.rewrite_force_virtual(vrefinfo) self.add_finish() - self.metainterp_sd.finish_setup(optimizer=optimizer) + self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info if vinfo is not None: vinfo.finish() if self.cpu.translate_support_code: @@ -244,11 +244,10 @@ remove_asserts=True, really_remove_asserts=True) - def build_meta_interp(self, CPUClass, translate_support_code=False, - view="auto", no_stats=False, - ProfilerClass=EmptyProfiler, **kwds): + def build_cpu(self, CPUClass, translate_support_code=False, + no_stats=False, **kwds): assert CPUClass is not None - opt = history.Options(**kwds) + self.opt = history.Options(**kwds) if no_stats: stats = history.NoStats() else: @@ -259,18 +258,18 @@ annhelper = self.annhelper else: annhelper = None - cpu = CPUClass(self.translator.rtyper, self.stats, opt, + cpu = CPUClass(self.translator.rtyper, self.stats, self.opt, translate_support_code, gcdescr=self.gcdescr) self.cpu = cpu - self.metainterp_sd = MetaInterpStaticData(self.portal_graph, # xxx - cpu, - self.stats, opt, + + def build_meta_interp(self, ProfilerClass): + self.metainterp_sd = MetaInterpStaticData(self.cpu, + self.opt, ProfilerClass=ProfilerClass, warmrunnerdesc=self) def make_exception_classes(self): - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(self.PORTAL_FUNCTYPE.ARGS)]) + class DoneWithThisFrameVoid(JitException): def __str__(self): return 'DoneWithThisFrameVoid()' @@ -304,18 +303,19 @@ return 'ExitFrameWithExceptionRef(%s)' % (self.value,) class ContinueRunningNormally(ContinueRunningNormallyBase): - def __init__(self, argboxes): - # accepts boxes as argument, but unpacks them immediately - # before we raise the exception -- the boxes' values will - # be modified in a 'finally' by restore_patched_boxes(). - from pypy.jit.metainterp.warmstate import unwrap - for i, name, ARG in portalfunc_ARGS: - v = unwrap(ARG, argboxes[i]) - setattr(self, name, v) - + def __init__(self, gi, gr, gf, ri, rr, rf): + # the six arguments are: lists of green ints, greens refs, + # green floats, red ints, red refs, and red floats. + self.green_int = gi + self.green_ref = gr + self.green_float = gf + self.red_int = ri + self.red_ref = rr + self.red_float = rf def __str__(self): - return 'ContinueRunningNormally(%s)' % ( - ', '.join(map(str, self.args)),) + return 'ContinueRunningNormally(%s, %s, %s, %s, %s, %s)' % ( + self.green_int, self.green_ref, self.green_float, + self.red_int, self.red_ref, self.red_float) self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt @@ -411,17 +411,10 @@ def make_args_specification(self): graph, block, index = self.jit_merge_point_pos op = block.operations[index] - args = op.args[2:] - ALLARGS = [] - self.green_args_spec = [] - self.red_args_types = [] - for i, v in enumerate(args): - TYPE = v.concretetype - ALLARGS.append(TYPE) - if i < len(self.jitdriver.greens): - self.green_args_spec.append(TYPE) - else: - self.red_args_types.append(history.getkind(TYPE)) + greens_v, reds_v = support.decode_hp_hint_args(op) + ALLARGS = [v.concretetype for v in (greens_v + reds_v)] + self.green_args_spec = [v.concretetype for v in greens_v] + self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] self.num_green_args = len(self.green_args_spec) RESTYPE = graph.getreturnvar().concretetype (self.JIT_ENTER_FUNCTYPE, @@ -443,7 +436,7 @@ continue op = block.operations[index] - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) args_v = greens_v + reds_v vlist = [Constant(jit_enter_fnptr, FUNCPTR)] + args_v @@ -500,13 +493,24 @@ # ____________________________________________________________ # Prepare the portal_runner() helper # + from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) self.portal_ptr = portal_ptr - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)]) - - + # + portalfunc_ARGS = [] + nums = {} + for i, ARG in enumerate(PORTALFUNC.ARGS): + if i < len(self.jitdriver.greens): + color = 'green' + else: + color = 'red' + attrname = '%s_%s' % (color, history.getkind(ARG)) + count = nums.get(attrname, 0) + nums[attrname] = count + 1 + portalfunc_ARGS.append((ARG, attrname, count)) + portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS) + # rtyper = self.translator.rtyper RESULT = PORTALFUNC.RESULT result_kind = history.getkind(RESULT) @@ -520,21 +524,22 @@ portal_ptr)(*args) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -550,8 +555,9 @@ self.PTR_PORTAL_FUNCTYPE.TO, self.PTR_PORTAL_FUNCTYPE.TO.ARGS, self.PTR_PORTAL_FUNCTYPE.TO.RESULT) + self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -565,22 +571,23 @@ fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) return ll_portal_runner(*args) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -607,7 +614,7 @@ op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v @@ -651,22 +658,8 @@ op.opname = 'direct_call' op.args[:3] = [closures[funcname]] - def rewrite_force_virtual(self): + def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': py.test.skip("rewrite_force_virtual: port it to ootype") all_graphs = self.translator.graphs - vrefinfo = self.metainterp_sd.virtualref_info vrefinfo.replace_force_virtual_with_call(all_graphs) - - -def decode_hp_hint_args(op): - # Returns (list-of-green-vars, list-of-red-vars) without Voids. - assert op.opname == 'jit_marker' - jitdriver = op.args[1].value - numgreens = len(jitdriver.greens) - numreds = len(jitdriver.reds) - greens_v = op.args[2:2+numgreens] - reds_v = op.args[2+numgreens:] - assert len(reds_v) == numreds - return ([v for v in greens_v if v.concretetype is not lltype.Void], - [v for v in reds_v if v.concretetype is not lltype.Void]) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/warmstate.py Tue Jun 8 19:48:40 2010 @@ -11,11 +11,26 @@ from pypy.rlib.jit import DEBUG_PROFILE from pypy.rlib.jit import BaseJitCell from pypy.rlib.debug import debug_start, debug_stop, debug_print -from pypy.jit.metainterp import support, history +from pypy.jit.metainterp import history +from pypy.jit.codewriter import support, heaptracker # ____________________________________________________________ @specialize.arg(0) +def specialize_value(TYPE, x): + """'x' must be a Signed, a GCREF or a Float. + This function casts it to a more specialized type, like Char or Ptr(..). + """ + INPUT = lltype.typeOf(x) + if INPUT is lltype.Signed: + return lltype.cast_primitive(TYPE, x) # XXX missing: Ptr(non-gc) + elif INPUT is lltype.Float: + assert TYPE is lltype.Float + return x + else: + return lltype.cast_opaque_ptr(TYPE, x) + + at specialize.arg(0) def unwrap(TYPE, box): if TYPE is lltype.Void: return None @@ -39,7 +54,7 @@ return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) - value = cpu.cast_adr_to_int(adr) + value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) @@ -180,7 +195,7 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = metainterp_sd.virtualizable_info + vinfo = self.warmrunnerdesc.virtualizable_info num_green_args = self.warmrunnerdesc.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() @@ -401,7 +416,7 @@ warmrunnerdesc = self.warmrunnerdesc cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.metainterp_sd.virtualizable_info + vinfo = warmrunnerdesc.virtualizable_info red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) # def set_future_values(*redargs): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tl/spli/interpreter.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tl/spli/interpreter.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tl/spli/interpreter.py Tue Jun 8 19:48:40 2010 @@ -24,7 +24,7 @@ unrolling_compare_dispatch_table = unrolling_iterable( enumerate(compare_ops)) -jitdriver = JitDriver(greens = ['code', 'instr_index'], +jitdriver = JitDriver(greens = ['instr_index', 'code'], reds = ['frame'], virtualizables = ['frame']) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tl.py Tue Jun 8 19:48:40 2010 @@ -56,7 +56,7 @@ def make_interp(supports_call): myjitdriver = JitDriver(greens = ['pc', 'code'], - reds = ['stack', 'inputarg'], + reds = ['inputarg', 'stack'], virtualizables = ['stack']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tla/tla.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tla/tla.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tla/tla.py Tue Jun 8 19:48:40 2010 @@ -71,10 +71,10 @@ # ____________________________________________________________ -def get_printable_location(bytecode, pc): +def get_printable_location(pc, bytecode): return str(pc) -jitdriver = JitDriver(greens=['bytecode', 'pc'], +jitdriver = JitDriver(greens=['pc', 'bytecode'], reds=['self'], virtualizables=['self'], get_printable_location=get_printable_location) Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlc.py Tue Jun 8 19:48:40 2010 @@ -226,7 +226,7 @@ def make_interp(supports_call, jitted=True): - myjitdriver = JitDriver(greens = ['code', 'pc'], + myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['frame', 'pool']) def interp(code='', pc=0, inputarg=0, pool=None): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlr.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlr.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tl/tlr.py Tue Jun 8 19:48:40 2010 @@ -12,7 +12,7 @@ NEG_A = 8 class TLRJitDriver(JitDriver): - greens = ['bytecode', 'pc'] + greens = ['pc', 'bytecode'] reds = ['a', 'regs'] tlrjitdriver = TLRJitDriver() Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tool/jitoutput.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tool/jitoutput.py Tue Jun 8 19:48:40 2010 @@ -21,8 +21,6 @@ (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), - (('blackholed_ops.total',), '^blackholed ops:\s+(\d+)$'), - (('blackholed_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), (('forcings',), '^forcings:\s+(\d+)$'), @@ -62,7 +60,6 @@ def __init__(self): self.ops = Ops() self.recorded_ops = Ops() - self.blackholed_ops = Ops() self.abort = Aborts() def parse_prof(output): Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/tool/test/test_jitoutput.py Tue Jun 8 19:48:40 2010 @@ -41,8 +41,6 @@ assert info.recorded_ops.calls == 0 assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 - assert info.blackholed_ops.total == 0 - assert info.blackholed_ops.pure_calls == 0 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 0 @@ -59,8 +57,6 @@ calls: 3 pure calls: 2 guards: 1 -blackholed ops: 5 - pure calls: 3 opt ops: 6 opt guards: 1 forcings: 1 @@ -87,8 +83,6 @@ assert info.recorded_ops.calls == 3 assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 - assert info.blackholed_ops.total == 5 - assert info.blackholed_ops.pure_calls == 3 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 1 Modified: pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/policy.py Tue Jun 8 19:48:40 2010 @@ -1,4 +1,4 @@ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy class PyPyJitPolicy(JitPolicy): Modified: pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/test/test_pypy_c.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/test/test_pypy_c.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/module/pypyjit/test/test_pypy_c.py Tue Jun 8 19:48:40 2010 @@ -222,7 +222,7 @@ while i < n+OFFSET: i = f(f(i)) return i - ''', 96, + ''', 98, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOAD_GLOBAL") @@ -263,7 +263,7 @@ x = a.f(i) i = a.f(x) return i - ''', 92, + ''', 93, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOOKUP_METHOD") @@ -308,7 +308,7 @@ x = a.f(i) i = a.g(x) return i - ''', 105, + ''', 106, ([20], 20), ([31], 31)) ops = self.get_by_bytecode("LOOKUP_METHOD") Modified: pypy/branch/blackhole-improvement-merge/pypy/objspace/flow/model.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/objspace/flow/model.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/objspace/flow/model.py Tue Jun 8 19:48:40 2010 @@ -416,13 +416,14 @@ lst.append(link) return result -def copygraph(graph, shallow=False, varmap={}): +def copygraph(graph, shallow=False, varmap={}, shallowvars=False): "Make a copy of a flow graph." blockmap = {} varmap = varmap.copy() + shallowvars = shallowvars or shallow def copyvar(v): - if shallow: + if shallowvars: return v try: return varmap[v] Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/llinterp.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/llinterp.py Tue Jun 8 19:48:40 2010 @@ -111,16 +111,14 @@ self.traceback_frames = [] lines = [] for frame in frames: - logline = frame.graph.name + logline = frame.graph.name + "()" if frame.curr_block is None: logline += " " lines.append(logline) continue try: - logline += " " + self.typer.annotator.annotated[frame.curr_block].__module__ - except (KeyError, AttributeError): - # if the graph is from the GC it was not produced by the same - # translator :-( + logline += " " + self.typer.annotator.annotated[frame.curr_block].func.__module__ + except (KeyError, AttributeError, TypeError): logline += " " lines.append(logline) for i, operation in enumerate(frame.curr_block.operations): @@ -808,9 +806,9 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) - def op_cast_adr_to_int(self, adr): + def op_cast_adr_to_int(self, adr, mode): checkadr(adr) - return llmemory.cast_adr_to_int(adr) + return llmemory.cast_adr_to_int(adr, mode) def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/ll2ctypes.py Tue Jun 8 19:48:40 2010 @@ -505,7 +505,7 @@ # additionally, this adds mess to __del__ "semantics" _all_callbacks = {} _all_callbacks_results = [] -_callback2obj = {} +_int2obj = {} _callback_exc_info = None def get_rtyper(): @@ -522,6 +522,13 @@ """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) + if isinstance(llobj, llmemory.AddressAsInt): + cobj = ctypes.cast(lltype2ctypes(llobj.adr), ctypes.c_void_p) + res = intmask(cobj.value) + _int2obj[res] = llobj.adr.ptr._obj + return res + if isinstance(llobj, llmemory.fakeaddress): + llobj = llobj.ptr or 0 T = lltype.typeOf(llobj) @@ -614,8 +621,9 @@ else: ctypes_func_type = get_ctypes_type(T) res = ctypes_func_type(callback) - _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container _all_callbacks[key] = res + key2 = intmask(ctypes.cast(res, ctypes.c_void_p).value) + _int2obj[key2] = container return res index = 0 @@ -724,9 +732,9 @@ container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): - cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value - if cobjkey in _callback2obj: - container = _callback2obj[cobjkey] + cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value) + if cobjkey in _int2obj: + container = _int2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), @@ -993,6 +1001,8 @@ """Cast a value to a result type, trying to use the same rules as C.""" if not isinstance(RESTYPE, lltype.LowLevelType): raise TypeError("rffi.cast() first arg should be a TYPE") + if isinstance(value, llmemory.AddressAsInt): + value = value.adr if isinstance(value, llmemory.fakeaddress): value = value.ptr or 0 TYPE1 = lltype.typeOf(value) Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llarena.py Tue Jun 8 19:48:40 2010 @@ -223,7 +223,8 @@ else: return self.arena._getid() < arena._getid() - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): + assert not symbolic return self.arena._getid() + self.offset Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/llmemory.py Tue Jun 8 19:48:40 2010 @@ -7,6 +7,7 @@ import weakref from pypy.rlib.objectmodel import Symbolic from pypy.rpython.lltypesystem import lltype +from pypy.tool.uid import uid class AddressOffset(Symbolic): @@ -478,11 +479,14 @@ else: return lltype.nullptr(EXPECTED_TYPE.TO) - def _cast_to_int(self): - # This is a bit annoying. We want this method to still work when the - # pointed-to object is dead + def _cast_to_int(self, symbolic=False): if self: - return self.ptr._cast_to_int(False) + if symbolic: + return AddressAsInt(self) + else: + # This is a bit annoying. We want this method to still work + # when the pointed-to object is dead + return self.ptr._cast_to_int(False) else: return 0 @@ -496,6 +500,29 @@ # ____________________________________________________________ +class AddressAsInt(Symbolic): + # a symbolic, rendered as an address cast to an integer. + def __init__(self, adr): + self.adr = adr + def annotation(self): + from pypy.annotation import model + return model.SomeInteger() + def lltype(self): + return lltype.Signed + def __eq__(self, other): + return self.adr == cast_int_to_adr(other) + def __ne__(self, other): + return self.adr != cast_int_to_adr(other) + def __nonzero__(self): + return bool(self.adr) + def __repr__(self): + try: + return '' % (self.adr.ptr,) + except AttributeError: + return '' % (uid(self),) + +# ____________________________________________________________ + class NullAddressError(Exception): pass @@ -603,12 +630,31 @@ def cast_adr_to_ptr(adr, EXPECTED_TYPE): return adr._cast_to_ptr(EXPECTED_TYPE) -def cast_adr_to_int(adr): - return adr._cast_to_int() +def cast_adr_to_int(adr, mode="emulated"): + # The following modes are supported before translation (after + # translation, it's all just a cast): + # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some + # number based on id(). The difference is that it works even if the + # address is that of a dead object. + # * mode="symbolic": returns an AddressAsInt instance, which can only be + # cast back to an address later. + # * mode="forced": uses rffi.cast() to return a real number. + assert mode in ("emulated", "symbolic", "forced") + res = adr._cast_to_int(symbolic = (mode != "emulated")) + if mode == "forced": + from pypy.rpython.lltypesystem.rffi import cast + res = cast(lltype.Signed, res) + return res _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + if isinstance(int, AddressAsInt): + return int.adr + try: + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + except ValueError: + from pypy.rpython.lltypesystem import ll2ctypes + ptr = ll2ctypes._int2obj[int]._as_ptr() return cast_ptr_to_adr(ptr) # ____________________________________________________________ Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lloperation.py Tue Jun 8 19:48:40 2010 @@ -263,7 +263,7 @@ 'uint_rshift': LLOp(canfold=True), 'uint_xor': LLOp(canfold=True), - 'float_is_true': LLOp(canfold=True), + 'float_is_true': LLOp(canfold=True), # it really means "x != 0.0" 'float_neg': LLOp(canfold=True), 'float_abs': LLOp(canfold=True), @@ -410,7 +410,7 @@ 'cast_ptr_to_adr': LLOp(sideeffects=False), 'cast_adr_to_ptr': LLOp(canfold=True), 'cast_adr_to_int': LLOp(sideeffects=False), - 'cast_int_to_adr': LLOp(canfold=True), # not implemented in llinterp + 'cast_int_to_adr': LLOp(canfold=True), 'get_group_member': LLOp(canfold=True), 'get_next_group_member':LLOp(canfold=True), Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/lltype.py Tue Jun 8 19:48:40 2010 @@ -301,9 +301,17 @@ class RttiStruct(Struct): _runtime_type_info = None + def _install_extras(self, rtti=False, **kwds): + if rtti: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, + name=self._name, + about=self)._obj + Struct._install_extras(self, **kwds) + def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + raise TypeError("attachRuntimeTypeInfo: %r must have been built " + "with the rtti=True argument" % (self,)) if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -1877,7 +1885,8 @@ def cast_int_to_ptr(PTRTYPE, oddint): if oddint == 0: return nullptr(PTRTYPE.TO) - assert oddint & 1, "only odd integers can be cast back to ptr" + if not (oddint & 1): + raise ValueError("only odd integers can be cast back to ptr") return _ptr(PTRTYPE, oddint, solid=True) def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/rclass.py Tue Jun 8 19:48:40 2010 @@ -13,7 +13,7 @@ Ptr, Struct, GcStruct, malloc, \ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ - Array, Char, Void, attachRuntimeTypeInfo, \ + Array, Char, Void, \ FuncType, Bool, Signed, functionptr, FuncType, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -60,7 +60,8 @@ CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), hints = {'immutable': True, 'shouldntbenull': True, - 'typeptr': True}) + 'typeptr': True}, + rtti = True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), @@ -72,7 +73,7 @@ hints = {'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) -NONGCOBJECTPTR = Ptr(OBJECT) +NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} @@ -348,18 +349,20 @@ if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) + kwds = {} + if self.gcflavor == 'gc': + kwds['rtti'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, - *llfields) + *llfields, + **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields - if self.gcflavor == 'gc': - attachRuntimeTypeInfo(self.object_type) def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Tue Jun 8 19:48:40 2010 @@ -1242,6 +1242,15 @@ res = interpret(f, []) assert res == 6 + def test_force_to_int(self): + S = lltype.Struct('S') + p = lltype.malloc(S, flavor='raw') + a = llmemory.cast_ptr_to_adr(p) + i = llmemory.cast_adr_to_int(a, "forced") + assert type(i) is int + assert i == llmemory.cast_adr_to_int(a, "forced") + lltype.free(p, flavor='raw') + class TestPlatform(object): def test_lib_on_libpaths(self): from pypy.translator.platform import platform Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_llmemory.py Tue Jun 8 19:48:40 2010 @@ -624,3 +624,24 @@ # the following line crashes if the array is dead ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) ptr1[0] = NULL + +def test_cast_adr_to_int(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + i = cast_adr_to_int(adr, mode="symbolic") + assert isinstance(i, AddressAsInt) + assert cast_int_to_adr(i) == adr + assert cast_adr_to_int(NULL, mode="symbolic") == 0 + assert cast_int_to_adr(0) == NULL + # + i = cast_adr_to_int(adr, mode="emulated") + assert type(i) is int + i = cast_adr_to_int(NULL, mode="emulated") + assert type(i) is int and i == 0 + # + i = cast_adr_to_int(adr, mode="forced") + assert type(i) is int + #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details + i = cast_adr_to_int(NULL, mode="forced") + assert type(i) is int and i == 0 Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/lltypesystem/test/test_lltype.py Tue Jun 8 19:48:40 2010 @@ -363,22 +363,25 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) py.test.raises(ValueError, "getRuntimeTypeInfo(S)") - pinf0 = attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) + pinfx = getRuntimeTypeInfo(S) + pinf0 = attachRuntimeTypeInfo(S) # no-op, really assert pinf0._obj.about == S + assert pinf0 == pinfx pinf = getRuntimeTypeInfo(S) assert pinf == pinf0 pinf1 = getRuntimeTypeInfo(S) assert pinf == pinf1 - Z = GcStruct('z', ('x', Unsigned)) - attachRuntimeTypeInfo(Z) + Z = GcStruct('z', ('x', Unsigned), rtti=True) assert getRuntimeTypeInfo(Z) != pinf0 - Sbis = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(Sbis) + Sbis = GcStruct('s', ('x', Signed), rtti=True) assert getRuntimeTypeInfo(Sbis) != pinf0 assert Sbis != S # the attached runtime type info distinguishes them + Ster = GcStruct('s', ('x', Signed), rtti=True) + assert Sbis != Ster # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -399,12 +402,12 @@ assert pinf._obj.query_funcptr == qp def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) attachRuntimeTypeInfo(S) s = malloc(S) s.x = 0 assert runtime_type_info(s) == getRuntimeTypeInfo(S) - S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + S1 = GcStruct('s1', ('sub', S), ('x', Signed), rtti=True) attachRuntimeTypeInfo(S1) s1 = malloc(S1) s1.sub.x = 0 Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_boehm.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_boehm.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_boehm.py Tue Jun 8 19:48:40 2010 @@ -40,7 +40,7 @@ assert f is not None def test_boehm_finalizer___del__(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -58,7 +58,8 @@ assert f is not None def test_boehm_finalizer_nomix___del___and_pyobj(): - S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) + S = lltype.GcStruct("S", ('x', lltype.Signed), + ('y', lltype.Ptr(lltype.PyObject)), rtti=True) def f(s): s.x = 1 def type_info_S(p): Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/gctransform/test/test_refcounting.py Tue Jun 8 19:48:40 2010 @@ -175,7 +175,7 @@ assert len(ops['gc_free']) == 1 def test_deallocator_with_destructor(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -192,9 +192,9 @@ graph, t = make_deallocator(S) def test_caching_dynamic_deallocator(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) - T = lltype.GcStruct("T", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) + S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) + T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/memory/test/test_lldict.py Tue Jun 8 19:48:40 2010 @@ -100,7 +100,7 @@ _TYPE = llmemory.Address def __init__(self, intval): self.intval = intval - def _cast_to_int(self): + def _cast_to_int(self, symbolic="?"): return self.intval def __repr__(self): return '' % (self.intval & (sys.maxint*2+1),) Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/raddress.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/raddress.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/raddress.py Tue Jun 8 19:48:40 2010 @@ -7,6 +7,8 @@ from pypy.rpython.rptr import PtrRepr from pypy.rpython.lltypesystem import lltype from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.objectmodel import we_are_translated + class __extend__(annmodel.SomeAddress): def rtyper_makerepr(self, rtyper): @@ -33,7 +35,7 @@ def ll_str(self, a): from pypy.rpython.lltypesystem.rstr import ll_str - id = cast_adr_to_int(a) + id = ll_addrhash(a) return ll_str.ll_int2hex(r_uint(id), True) def rtype_getattr(self, hop): @@ -55,7 +57,7 @@ get_ll_fasthash_function = get_ll_hash_function def ll_addrhash(addr1): - return cast_adr_to_int(addr1) + return cast_adr_to_int(addr1, "forced") address_repr = AddressRepr() Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/rbuiltin.py Tue Jun 8 19:48:40 2010 @@ -637,9 +637,14 @@ def rtype_cast_adr_to_int(hop): assert isinstance(hop.args_r[0], raddress.AddressRepr) - adr, = hop.inputargs(hop.args_r[0]) + adr = hop.inputarg(hop.args_r[0], arg=0) + if len(hop.args_s) == 1: + mode = "emulated" + else: + mode = hop.args_s[1].const hop.exception_cannot_occur() - return hop.genop('cast_adr_to_int', [adr], + return hop.genop('cast_adr_to_int', + [adr, hop.inputconst(lltype.Void, mode)], resulttype = lltype.Signed) def rtype_cast_int_to_adr(hop): Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_exception.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_exception.py Tue Jun 8 19:48:40 2010 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.llinterp import LLException +from pypy.rpython.error import MissingRTypeOperation class MyException(Exception): pass @@ -125,7 +126,18 @@ class TestLLtype(BaseTestException, LLRtypeMixin): - pass + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + def g(): + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise lle # instead, must cast back from a base ptr to an instance + def f(): + try: + g() + except OverflowError: + return 42 + py.test.raises(MissingRTypeOperation, self.interpret, f, []) class TestOOtype(BaseTestException, OORtypeMixin): pass Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_llann.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_llann.py Tue Jun 8 19:48:40 2010 @@ -343,8 +343,7 @@ assert s.items[1].const == 3 def test_getRuntimeTypeInfo(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(): return getRuntimeTypeInfo(S) s = self.annotate(llf, []) @@ -353,8 +352,7 @@ assert s.const == getRuntimeTypeInfo(S) def test_runtime_type_info(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(p): return runtime_type_info(p) s = self.annotate(llf, [annmodel.SomePtr(Ptr(S))]) Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rdict.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rdict.py Tue Jun 8 19:48:40 2010 @@ -781,6 +781,24 @@ assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2) assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3) + def test_dict_of_addresses(self): + from pypy.rpython.lltypesystem import llmemory + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def func(i): + d = {} + d[llmemory.cast_ptr_to_adr(a)] = 123 + d[llmemory.cast_ptr_to_adr(b)] = 456 + if i > 5: + key = llmemory.cast_ptr_to_adr(a) + else: + key = llmemory.cast_ptr_to_adr(b) + return d[key] + + assert self.interpret(func, [3]) == 456 + def test_prebuilt_list_of_addresses(self): from pypy.rpython.lltypesystem import llmemory Modified: pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/rpython/test/test_rptr.py Tue Jun 8 19:48:40 2010 @@ -36,8 +36,7 @@ assert s.ll_ptrtype == PS2 def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def ll_example(p): return (runtime_type_info(p), runtime_type_info(p) == getRuntimeTypeInfo(S)) @@ -176,6 +175,31 @@ res = interpret(fn, [5]) assert res is True +def test_cast_adr_to_int(): + S = Struct('S') + p = malloc(S, immortal=True) + def fn(n): + a = llmemory.cast_ptr_to_adr(p) + if n == 2: + return llmemory.cast_adr_to_int(a, "emulated") + elif n == 4: + return llmemory.cast_adr_to_int(a, "symbolic") + else: + return llmemory.cast_adr_to_int(a, "forced") + + res = interpret(fn, [2]) + assert type(res) is int + assert res == cast_ptr_to_int(p) + # + res = interpret(fn, [4]) + assert isinstance(res, llmemory.AddressAsInt) + assert llmemory.cast_int_to_adr(res) == llmemory.cast_ptr_to_adr(p) + # + res = interpret(fn, [6]) + assert type(res) is int + from pypy.rpython.lltypesystem import rffi + assert res == rffi.cast(Signed, p) + def test_flavored_malloc(): T = GcStruct('T', ('y', Signed)) def fn(n): Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/c/primitive.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/c/primitive.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/c/primitive.py Tue Jun 8 19:48:40 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ CompositeOffset, ArrayLengthOffset, \ - GCHeaderOffset, GCREF + GCHeaderOffset, GCREF, AddressAsInt from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation from pypy.translator.c.support import cdecl, barebonearray @@ -61,6 +61,8 @@ name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) + elif isinstance(value, AddressAsInt): + return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r"%value) if value is None: Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/c/src/address.h ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/c/src/address.h (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/c/src/address.h Tue Jun 8 19:48:40 2010 @@ -16,5 +16,5 @@ #define OP_ADR_LT(x,y,r) r = ((x) < (y)) #define OP_ADR_GE(x,y,r) r = ((x) >= (y)) -#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x) -#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) +#define OP_CAST_ADR_TO_INT(x, mode, r) r = ((long)x) +#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_genc.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_genc.py Tue Jun 8 19:48:40 2010 @@ -144,10 +144,8 @@ assert f1() == '\x00' def test_runtime_type_info(): - S = GcStruct('s', ('is_actually_s1', Bool)) - S1 = GcStruct('s1', ('sub', S)) - attachRuntimeTypeInfo(S) - attachRuntimeTypeInfo(S1) + S = GcStruct('s', ('is_actually_s1', Bool), rtti=True) + S1 = GcStruct('s1', ('sub', S), rtti=True) def rtti_S(p): if p.is_actually_s1: return getRuntimeTypeInfo(S1) Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_lladdresses.py Tue Jun 8 19:48:40 2010 @@ -193,3 +193,42 @@ fc = compile(f, [int]) res = fc(42) assert res == 0 + +def test_cast_int_to_adr(): + S = lltype.Struct("S", ("x", lltype.Signed)) + s = lltype.malloc(S, immortal=True) + s.x = 42 + integer = cast_adr_to_int(cast_ptr_to_adr(s), mode="symbolic") + def f(n): + if n > 1: + i = integer + else: + i = 123 # nonsense, but never used + print "hello world" # prevent constant-folding + adr = cast_int_to_adr(i) + s = cast_adr_to_ptr(adr, lltype.Ptr(S)) + return s.x + fc = compile(f, [int]) + res = fc(5) + assert res == 42 + +def test_dict_of_addresses(): + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def f(i): + d = {} + d[cast_ptr_to_adr(a)] = 123 + d[cast_ptr_to_adr(b)] = 456 + if i > 5: + key = cast_ptr_to_adr(a) + else: + key = cast_ptr_to_adr(b) + return d[key] + + fc = compile(f, [int]) + res = fc(-77) + assert res == 456 + res = fc(77) + assert res == 123 Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_refcount.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_refcount.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/c/test/test_refcount.py Tue Jun 8 19:48:40 2010 @@ -130,9 +130,8 @@ def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: - S = lltype.GcStruct('S', ('x', lltype.Signed)) + S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): Modified: pypy/branch/blackhole-improvement-merge/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/translator/tool/make_dot.py Tue Jun 8 19:48:40 2010 @@ -152,7 +152,7 @@ shape = "octagon" if block.exitswitch is not None: - lines.append("exitswitch: %s" % block.exitswitch) + lines.append("exitswitch: %s" % (block.exitswitch,)) iargs = " ".join(map(repr, block.inputargs)) if self.VERBOSE: From afa at codespeak.net Tue Jun 8 20:27:38 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 20:27:38 +0200 (CEST) Subject: [pypy-svn] r75212 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608182738.CB5EB282BDE@codespeak.net> Author: afa Date: Tue Jun 8 20:27:36 2010 New Revision: 75212 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: more refactoring Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 20:27:36 2010 @@ -357,6 +357,12 @@ from pypy.module import cpyext return eval(self.expr) + def get_structtype_for_ctype(self): + from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr + from pypy.module.cpyext.datetime import PyDateTime_CAPI + return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, + "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[self.type] + class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name + '#' @@ -366,6 +372,12 @@ def get_global_code_for_bridge(self): return [] + def get_type_for_declaration(self): + return 'PyObject' + + needs_hidden_global_structure = False + is_pyobject = True + class GlobalStructurePointer(BaseGlobalObject): def __init__(self, name, type, expr): self.name = name @@ -381,6 +393,12 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value + def get_type_for_declaration(self): + return self.type + + needs_hidden_global_structure = True + is_pyobject = False + class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): self.name = 'PyExc_' + exc_name @@ -391,6 +409,12 @@ def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type[:-1], self.name)] + def get_type_for_declaration(self): + return 'PyObject*' + + needs_hidden_global_structure = True + is_pyobject = True + class GlobalTypeObject(BaseGlobalObject): def __init__(self, name, expr): self.name = 'Py%s_Type#' % (name,) @@ -400,6 +424,12 @@ def get_global_code_for_bridge(self): return [] + def get_type_for_declaration(self): + return 'PyTypeObject' + + needs_hidden_global_structure = False + is_pyobject = True + GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') @@ -444,12 +474,6 @@ 'Py%sObject' % (cpyname, )) build_exported_objects() -def get_structtype_for_ctype(ctype): - from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - from pypy.module.cpyext.datetime import PyDateTime_CAPI - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, - "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] - PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) # It is important that these PyObjects are allocated in a raw fashion @@ -710,11 +734,7 @@ if isinstance(obj, GlobalStructurePointer): obj.set_value_in_ctypes_dll(bridge, value) elif obj.type in ('PyObject*', 'PyTypeObject*'): - if obj.name.endswith('#'): - name = obj.name[:-1] - else: - name = obj.name - + name = obj.name.replace('#', '') name = name.replace('Py', 'PyPy') if name.startswith('PyPyExc_'): @@ -805,13 +825,8 @@ functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) for obj in GLOBALS.values(): - name = obj.name - type = obj.type - if obj.name.endswith('#'): - name = name.replace("#", "") - type = type.replace("*", "") - elif name.startswith('PyExc_'): - type = 'PyObject*' + name = obj.name.replace("#", "") + type = obj.get_type_for_declaration() pypy_decls.append('PyAPI_DATA(%s) %s;' % (type, name)) pypy_decls.append("#ifdef __cplusplus") @@ -845,14 +860,13 @@ struct_file = udir.join('pypy_structs.c') structs = ["#include "] for obj in GLOBALS.values(): - if obj.name.endswith('#'): - structs.append('%s %s;' % (obj.type[:-1], obj.name[:-1])) - elif obj.name.startswith('PyExc_'): - structs.append('extern PyTypeObject _%s;' % (obj.name,)) - structs.append('PyObject* %s = (PyObject*)&_%s;' % (obj.name, obj.name)) - elif obj.type == 'PyDateTime_CAPI*': - structs.append('extern %s _%s;' % (obj.type[:-1], obj.name)) - structs.append('%s %s = &_%s;' % (obj.type, obj.name, obj.name)) + type = obj.get_type_for_declaration() + name = obj.name.replace('#', '') + if not obj.needs_hidden_global_structure: + structs.append('%s %s;' % (type, name)) + else: + structs.append('extern %s _%s;' % (obj.type[:-1], name)) + structs.append('%s %s = (%s)&_%s;' % (type, name, type, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -897,17 +911,12 @@ # populate static data for obj in GLOBALS.values(): name = obj.name.replace("#", "") - if name.startswith('PyExc_'): + if obj.needs_hidden_global_structure: name = '_' + name value = obj.eval(space) - if obj.type in ('PyObject*', 'PyTypeObject*'): - struct_ptr = make_ref(space, w_obj) - elif obj.type == 'PyDateTime_CAPI*': - struct_ptr = w_obj - name = '_' + name - else: - assert False, "Unknown static data: %s %s" % (obj.type, name) - struct = rffi.cast(get_structtype_for_ctype(obj.type), struct_ptr)._obj + if obj.is_pyobject: + value = make_ref(space, value) + struct = rffi.cast(obj.get_structtype_for_ctype(), value)._obj struct._compilation_info = eci export_struct(name, struct) From afa at codespeak.net Tue Jun 8 20:38:57 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 20:38:57 +0200 (CEST) Subject: [pypy-svn] r75213 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608183857.54846282BDE@codespeak.net> Author: afa Date: Tue Jun 8 20:38:55 2010 New Revision: 75213 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Finally: remove this '#' at the end of the type name. Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 20:38:55 2010 @@ -365,7 +365,7 @@ class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): - self.name = name + '#' + self.name = name self.type = 'PyObject*' self.expr = expr @@ -417,7 +417,7 @@ class GlobalTypeObject(BaseGlobalObject): def __init__(self, name, expr): - self.name = 'Py%s_Type#' % (name,) + self.name = 'Py%s_Type' % (name,) self.type = 'PyTypeObject*' self.expr = expr @@ -734,8 +734,7 @@ if isinstance(obj, GlobalStructurePointer): obj.set_value_in_ctypes_dll(bridge, value) elif obj.type in ('PyObject*', 'PyTypeObject*'): - name = obj.name.replace('#', '') - name = name.replace('Py', 'PyPy') + name = obj.name.replace('Py', 'PyPy') if name.startswith('PyPyExc_'): # we already have the pointer @@ -772,7 +771,6 @@ continue if not rename: continue - name = name.replace("#", "") newname = name.replace('Py', 'PyPy') if not rename: newname = name @@ -782,9 +780,7 @@ renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols - else: - export_symbols[:] = [sym.replace("#", "") for sym in export_symbols] - + # Generate defines for macro_name, size in [ ("SIZEOF_LONG_LONG", rffi.LONGLONG), @@ -825,7 +821,7 @@ functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) for obj in GLOBALS.values(): - name = obj.name.replace("#", "") + name = obj.name type = obj.get_type_for_declaration() pypy_decls.append('PyAPI_DATA(%s) %s;' % (type, name)) @@ -861,7 +857,7 @@ structs = ["#include "] for obj in GLOBALS.values(): type = obj.get_type_for_declaration() - name = obj.name.replace('#', '') + name = obj.name if not obj.needs_hidden_global_structure: structs.append('%s %s;' % (type, name)) else: @@ -910,7 +906,7 @@ # populate static data for obj in GLOBALS.values(): - name = obj.name.replace("#", "") + name = obj.name if obj.needs_hidden_global_structure: name = '_' + name value = obj.eval(space) From afa at codespeak.net Tue Jun 8 22:23:56 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 22:23:56 +0200 (CEST) Subject: [pypy-svn] r75214 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608202356.DB5F0282BF9@codespeak.net> Author: afa Date: Tue Jun 8 22:23:54 2010 New Revision: 75214 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: More refactoring Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 22:23:54 2010 @@ -357,6 +357,10 @@ from pypy.module import cpyext return eval(self.expr) + def get_data_declaration(self): + type = self.get_type_for_declaration() + return 'PyAPI_DATA(%s) %s;' % (type, self.name) + def get_structtype_for_ctype(self): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr from pypy.module.cpyext.datetime import PyDateTime_CAPI @@ -369,14 +373,16 @@ self.type = 'PyObject*' self.expr = expr + needs_hidden_global_structure = False def get_global_code_for_bridge(self): return [] def get_type_for_declaration(self): return 'PyObject' - needs_hidden_global_structure = False is_pyobject = True + def get_structtype_for_ctype(self): + return PyObject class GlobalStructurePointer(BaseGlobalObject): def __init__(self, name, type, expr): @@ -384,8 +390,9 @@ self.type = type self.expr = expr + needs_hidden_global_structure = True def get_global_code_for_bridge(self): - return ['%s _%s;' % (self.type, self.name)] + return ['%s _%s;' % (self.type[:-1], self.name)] def set_value_in_ctypes_dll(self, dll, value): name = self.name.replace('Py', 'PyPy') @@ -396,8 +403,10 @@ def get_type_for_declaration(self): return self.type - needs_hidden_global_structure = True is_pyobject = False + def get_structtype_for_ctype(self): + from pypy.module.cpyext.datetime import PyDateTime_CAPI + return PyDateTime_CAPI # XXX class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): @@ -406,14 +415,17 @@ self.expr = ('space.gettypeobject(interp_exceptions.W_%s.typedef)' % (exc_name,)) + needs_hidden_global_structure = True def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type[:-1], self.name)] def get_type_for_declaration(self): return 'PyObject*' - needs_hidden_global_structure = True is_pyobject = True + def get_structtype_for_ctype(self): + from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr + return PyTypeObjectPtr class GlobalTypeObject(BaseGlobalObject): def __init__(self, name, expr): @@ -421,14 +433,16 @@ self.type = 'PyTypeObject*' self.expr = expr + needs_hidden_global_structure = False def get_global_code_for_bridge(self): return [] def get_type_for_declaration(self): return 'PyTypeObject' - needs_hidden_global_structure = False is_pyobject = True + def get_structtype_for_ctype(self): + return PyTypeObjectPtr GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') @@ -727,7 +741,7 @@ bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) # populate static data - for obj in GLOBALS.values(): + for name, obj in GLOBALS.iteritems(): value = obj.eval(space) INTERPLEVEL_API[name] = value @@ -821,9 +835,7 @@ functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) for obj in GLOBALS.values(): - name = obj.name - type = obj.get_type_for_declaration() - pypy_decls.append('PyAPI_DATA(%s) %s;' % (type, name)) + pypy_decls.append(obj.get_data_declaration()) pypy_decls.append("#ifdef __cplusplus") pypy_decls.append("}") @@ -855,9 +867,8 @@ # Generate definitions for global structures struct_file = udir.join('pypy_structs.c') structs = ["#include "] - for obj in GLOBALS.values(): + for name, obj in GLOBALS.iteritems(): type = obj.get_type_for_declaration() - name = obj.name if not obj.needs_hidden_global_structure: structs.append('%s %s;' % (type, name)) else: @@ -905,8 +916,7 @@ run_bootstrap_functions(space) # populate static data - for obj in GLOBALS.values(): - name = obj.name + for name, obj in GLOBALS.iteritems(): if obj.needs_hidden_global_structure: name = '_' + name value = obj.eval(space) From arigo at codespeak.net Tue Jun 8 22:33:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jun 2010 22:33:34 +0200 (CEST) Subject: [pypy-svn] r75215 - pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp Message-ID: <20100608203334.6AA4D282BF9@codespeak.net> Author: arigo Date: Tue Jun 8 22:33:32 2010 New Revision: 75215 Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py Log: Fix. Modified: pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/pyjitpl.py Tue Jun 8 22:33:32 2010 @@ -1729,7 +1729,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1740,7 +1740,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests From afa at codespeak.net Tue Jun 8 23:18:54 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:18:54 +0200 (CEST) Subject: [pypy-svn] r75216 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608211854.F2A0B282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:18:53 2010 New Revision: 75216 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Fix Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:18:53 2010 @@ -361,12 +361,6 @@ type = self.get_type_for_declaration() return 'PyAPI_DATA(%s) %s;' % (type, self.name) - def get_structtype_for_ctype(self): - from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - from pypy.module.cpyext.datetime import PyDateTime_CAPI - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, - "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[self.type] - class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name @@ -384,6 +378,13 @@ def get_structtype_for_ctype(self): return PyObject + def set_value_in_ctypes_dll(self, space, dll, value): + # it's a structure, get its adress + name = self.name.replace('Py', 'PyPy') + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + attach_and_track(space, py_obj, value) + class GlobalStructurePointer(BaseGlobalObject): def __init__(self, name, type, expr): self.name = name @@ -394,7 +395,7 @@ def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type[:-1], self.name)] - def set_value_in_ctypes_dll(self, dll, value): + def set_value_in_ctypes_dll(self, space, dll, value): name = self.name.replace('Py', 'PyPy') ptr = ctypes.c_void_p.in_dll(dll, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), @@ -406,7 +407,7 @@ is_pyobject = False def get_structtype_for_ctype(self): from pypy.module.cpyext.datetime import PyDateTime_CAPI - return PyDateTime_CAPI # XXX + return lltype.Ptr(PyDateTime_CAPI) # XXX class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): @@ -427,6 +428,13 @@ from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr return PyTypeObjectPtr + def set_value_in_ctypes_dll(self, space, dll, value): + # it's a pointer + name = self.name.replace('Py', 'PyPy') + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(dll, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) + attach_and_track(space, py_obj, value) + class GlobalTypeObject(BaseGlobalObject): def __init__(self, name, expr): self.name = 'Py%s_Type' % (name,) @@ -444,6 +452,13 @@ def get_structtype_for_ctype(self): return PyTypeObjectPtr + def set_value_in_ctypes_dll(self, space, dll, value): + # it's a structure, get its adress + name = self.name.replace('Py', 'PyPy') + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + attach_and_track(space, py_obj, value) + GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') @@ -744,23 +759,7 @@ for name, obj in GLOBALS.iteritems(): value = obj.eval(space) INTERPLEVEL_API[name] = value - - if isinstance(obj, GlobalStructurePointer): - obj.set_value_in_ctypes_dll(bridge, value) - elif obj.type in ('PyObject*', 'PyTypeObject*'): - name = obj.name.replace('Py', 'PyPy') - - if name.startswith('PyPyExc_'): - # we already have the pointer - in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) - py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) - else: - # we have a structure, get its address - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) - py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) - attach_and_track(space, py_obj, value) - else: - assert False, "Unknown static object: %s %s" % (typ, name) + obj.set_value_in_ctypes_dll(space, bridge, value) pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') From afa at codespeak.net Tue Jun 8 23:31:02 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:31:02 +0200 (CEST) Subject: [pypy-svn] r75217 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608213102.89828282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:31:00 2010 New Revision: 75217 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: more progress Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:31:00 2010 @@ -370,13 +370,12 @@ needs_hidden_global_structure = False def get_global_code_for_bridge(self): return [] - def get_type_for_declaration(self): return 'PyObject' - is_pyobject = True - def get_structtype_for_ctype(self): - return PyObject + def get_struct_to_export(self, space, value): + value = make_ref(space, value) + return value._obj def set_value_in_ctypes_dll(self, space, dll, value): # it's a structure, get its adress @@ -394,6 +393,12 @@ needs_hidden_global_structure = True def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type[:-1], self.name)] + def get_type_for_declaration(self): + return self.type + + def get_value_to_export(self, space, value): + from pypy.module.cpyext.datetime import PyDateTime_CAPI + struct = rffi.cast(lltype.Ptr(PyDateTime_CAPI), value)._obj def set_value_in_ctypes_dll(self, space, dll, value): name = self.name.replace('Py', 'PyPy') @@ -401,14 +406,6 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value - def get_type_for_declaration(self): - return self.type - - is_pyobject = False - def get_structtype_for_ctype(self): - from pypy.module.cpyext.datetime import PyDateTime_CAPI - return lltype.Ptr(PyDateTime_CAPI) # XXX - class GlobalExceptionPointer(BaseGlobalObject): def __init__(self, exc_name): self.name = 'PyExc_' + exc_name @@ -419,14 +416,12 @@ needs_hidden_global_structure = True def get_global_code_for_bridge(self): return ['%s _%s;' % (self.type[:-1], self.name)] - def get_type_for_declaration(self): return 'PyObject*' - is_pyobject = True - def get_structtype_for_ctype(self): + def get_value_to_export(self, space, value): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - return PyTypeObjectPtr + return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj def set_value_in_ctypes_dll(self, space, dll, value): # it's a pointer @@ -444,13 +439,12 @@ needs_hidden_global_structure = False def get_global_code_for_bridge(self): return [] - def get_type_for_declaration(self): return 'PyTypeObject' - is_pyobject = True - def get_structtype_for_ctype(self): - return PyTypeObjectPtr + def get_value_to_export(self, space, value): + from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr + return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj def set_value_in_ctypes_dll(self, space, dll, value): # it's a structure, get its adress @@ -919,9 +913,7 @@ if obj.needs_hidden_global_structure: name = '_' + name value = obj.eval(space) - if obj.is_pyobject: - value = make_ref(space, value) - struct = rffi.cast(obj.get_structtype_for_ctype(), value)._obj + struct = obj.get_value_to_export(space, value) struct._compilation_info = eci export_struct(name, struct) From afa at codespeak.net Tue Jun 8 23:31:58 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:31:58 +0200 (CEST) Subject: [pypy-svn] r75218 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608213158.0E806282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:31:56 2010 New Revision: 75218 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: remove unused argument Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:31:56 2010 @@ -707,7 +707,7 @@ from pypy.translator.c.database import LowLevelDatabase db = LowLevelDatabase() - generate_macros(export_symbols, rename=True, do_deref=True) + generate_macros(export_symbols, rename=True) # Structure declaration code members = [] @@ -768,7 +768,7 @@ setup_init_functions(eci) return modulename.new(ext='') -def generate_macros(export_symbols, rename=True, do_deref=True): +def generate_macros(export_symbols, rename=True): "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] @@ -899,7 +899,7 @@ from pypy.translator.c.database import LowLevelDatabase db = LowLevelDatabase() - generate_macros(export_symbols, rename=False, do_deref=False) + generate_macros(export_symbols, rename=False) functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include \n" + "\n".join(functions) From afa at codespeak.net Tue Jun 8 23:33:15 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:33:15 +0200 (CEST) Subject: [pypy-svn] r75219 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608213315.C2C7D282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:33:14 2010 New Revision: 75219 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Fix import. This code will eventually move to another place. Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:33:14 2010 @@ -374,6 +374,7 @@ return 'PyObject' def get_struct_to_export(self, space, value): + from pypy.module.cpyext.pyobject import make_ref value = make_ref(space, value) return value._obj @@ -420,6 +421,7 @@ return 'PyObject*' def get_value_to_export(self, space, value): + from pypy.module.cpyext.pyobject import make_ref from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj @@ -443,6 +445,7 @@ return 'PyTypeObject' def get_value_to_export(self, space, value): + from pypy.module.cpyext.pyobject import make_ref from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj From arigo at codespeak.net Tue Jun 8 23:42:58 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jun 2010 23:42:58 +0200 (CEST) Subject: [pypy-svn] r75220 - in pypy/trunk/pypy: annotation annotation/test jit/backend jit/backend/llgraph jit/backend/llgraph/test jit/backend/llsupport jit/backend/llsupport/test jit/backend/test jit/backend/x86 jit/backend/x86/test jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/test jit/tl jit/tl/spli jit/tl/tla jit/tool jit/tool/test module/pypyjit module/pypyjit/test objspace/flow rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gctransform/test rpython/memory/test rpython/test tool/algo tool/algo/test translator/c translator/c/src translator/c/test translator/tool Message-ID: <20100608214258.3E44E282BDE@codespeak.net> Author: arigo Date: Tue Jun 8 23:42:50 2010 New Revision: 75220 Added: pypy/trunk/pypy/jit/codewriter/ (props changed) - copied from r75215, pypy/branch/blackhole-improvement-merge/pypy/jit/codewriter/ pypy/trunk/pypy/jit/metainterp/blackhole.py - copied unchanged from r75215, pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/blackhole.py pypy/trunk/pypy/jit/metainterp/jitexc.py - copied unchanged from r75215, pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/jitexc.py pypy/trunk/pypy/jit/metainterp/test/test_immutable.py - copied unchanged from r75215, pypy/branch/blackhole-improvement-merge/pypy/jit/metainterp/test/test_immutable.py pypy/trunk/pypy/tool/algo/color.py - copied unchanged from r75215, pypy/branch/blackhole-improvement-merge/pypy/tool/algo/color.py pypy/trunk/pypy/tool/algo/test/test_color.py - copied unchanged from r75215, pypy/branch/blackhole-improvement-merge/pypy/tool/algo/test/test_color.py Removed: pypy/trunk/pypy/jit/metainterp/codewriter.py pypy/trunk/pypy/jit/metainterp/dump.py pypy/trunk/pypy/jit/metainterp/effectinfo.py pypy/trunk/pypy/jit/metainterp/heaptracker.py pypy/trunk/pypy/jit/metainterp/policy.py pypy/trunk/pypy/jit/metainterp/support.py pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py pypy/trunk/pypy/jit/metainterp/test/test_effectinfo.py pypy/trunk/pypy/jit/metainterp/test/test_support.py Modified: pypy/trunk/pypy/annotation/builtin.py pypy/trunk/pypy/annotation/description.py pypy/trunk/pypy/annotation/test/test_annrpython.py pypy/trunk/pypy/jit/backend/llgraph/llimpl.py pypy/trunk/pypy/jit/backend/llgraph/runner.py pypy/trunk/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/trunk/pypy/jit/backend/llsupport/descr.py pypy/trunk/pypy/jit/backend/llsupport/gc.py pypy/trunk/pypy/jit/backend/llsupport/llmodel.py pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py pypy/trunk/pypy/jit/backend/model.py pypy/trunk/pypy/jit/backend/test/runner_test.py pypy/trunk/pypy/jit/backend/test/test_ll_random.py pypy/trunk/pypy/jit/backend/test/test_random.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/backend/x86/ri386.py pypy/trunk/pypy/jit/backend/x86/runner.py pypy/trunk/pypy/jit/backend/x86/support.py pypy/trunk/pypy/jit/backend/x86/test/test_assembler.py pypy/trunk/pypy/jit/backend/x86/test/test_basic.py pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py pypy/trunk/pypy/jit/backend/x86/test/test_regalloc2.py pypy/trunk/pypy/jit/backend/x86/test/test_runner.py pypy/trunk/pypy/jit/backend/x86/test/test_send.py pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py pypy/trunk/pypy/jit/codewriter/test/ (props changed) pypy/trunk/pypy/jit/metainterp/compile.py pypy/trunk/pypy/jit/metainterp/executor.py pypy/trunk/pypy/jit/metainterp/history.py pypy/trunk/pypy/jit/metainterp/jitprof.py pypy/trunk/pypy/jit/metainterp/logger.py pypy/trunk/pypy/jit/metainterp/optimizefindnode.py pypy/trunk/pypy/jit/metainterp/optimizeopt.py pypy/trunk/pypy/jit/metainterp/optimizeutil.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/resoperation.py pypy/trunk/pypy/jit/metainterp/resume.py pypy/trunk/pypy/jit/metainterp/simple_optimize.py pypy/trunk/pypy/jit/metainterp/specnode.py pypy/trunk/pypy/jit/metainterp/test/oparser.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py pypy/trunk/pypy/jit/metainterp/test/test_compile.py pypy/trunk/pypy/jit/metainterp/test/test_exception.py pypy/trunk/pypy/jit/metainterp/test/test_executor.py pypy/trunk/pypy/jit/metainterp/test/test_history.py pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py pypy/trunk/pypy/jit/metainterp/test/test_list.py pypy/trunk/pypy/jit/metainterp/test/test_loop.py pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py pypy/trunk/pypy/jit/metainterp/test/test_recursive.py pypy/trunk/pypy/jit/metainterp/test/test_resume.py pypy/trunk/pypy/jit/metainterp/test/test_send.py pypy/trunk/pypy/jit/metainterp/test/test_slist.py pypy/trunk/pypy/jit/metainterp/test/test_string.py pypy/trunk/pypy/jit/metainterp/test/test_tl.py pypy/trunk/pypy/jit/metainterp/test/test_tlc.py pypy/trunk/pypy/jit/metainterp/test/test_virtual.py pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py pypy/trunk/pypy/jit/metainterp/test/test_virtualref.py pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py pypy/trunk/pypy/jit/metainterp/typesystem.py pypy/trunk/pypy/jit/metainterp/virtualizable.py pypy/trunk/pypy/jit/metainterp/virtualref.py pypy/trunk/pypy/jit/metainterp/warmspot.py pypy/trunk/pypy/jit/metainterp/warmstate.py pypy/trunk/pypy/jit/tl/spli/interpreter.py pypy/trunk/pypy/jit/tl/tl.py pypy/trunk/pypy/jit/tl/tla/tla.py pypy/trunk/pypy/jit/tl/tlc.py pypy/trunk/pypy/jit/tl/tlr.py pypy/trunk/pypy/jit/tool/jitoutput.py pypy/trunk/pypy/jit/tool/test/test_jitoutput.py pypy/trunk/pypy/module/pypyjit/policy.py pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py pypy/trunk/pypy/objspace/flow/model.py pypy/trunk/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/llarena.py pypy/trunk/pypy/rpython/lltypesystem/llmemory.py pypy/trunk/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/rpython/lltypesystem/lltype.py pypy/trunk/pypy/rpython/lltypesystem/rclass.py pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py pypy/trunk/pypy/rpython/memory/gctransform/test/test_boehm.py pypy/trunk/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/trunk/pypy/rpython/memory/test/test_lldict.py pypy/trunk/pypy/rpython/raddress.py pypy/trunk/pypy/rpython/rbuiltin.py pypy/trunk/pypy/rpython/test/test_exception.py pypy/trunk/pypy/rpython/test/test_llann.py pypy/trunk/pypy/rpython/test/test_rdict.py pypy/trunk/pypy/rpython/test/test_rptr.py pypy/trunk/pypy/translator/c/primitive.py pypy/trunk/pypy/translator/c/src/address.h pypy/trunk/pypy/translator/c/test/test_genc.py pypy/trunk/pypy/translator/c/test/test_lladdresses.py pypy/trunk/pypy/translator/c/test/test_refcount.py pypy/trunk/pypy/translator/tool/make_dot.py Log: Merge the branch/blackhole-improvement (via the blackhole-improvement-merge branch). The basic goal is to split pyjitpl.py in two: the normal tracer, and a faster version (in blackhole.py) dedicated to running in blackhole mode. The latter does no tracing, but is much faster. Gives good performance gains on examples which need to do a lot of blackholing. The number of changes is a bit huge though. The format of the static bytecodes used by the jit changed completely, and codewriter.py is now split among many files in the new directory pypy.jit.codewriter. There is also no longer ConstAddr, only ConstInt: prebuilt addresses are now turned into integers (which are symbolic, with the new class AddressAsInt, so they can be rendered by the C translation backend). Various related changes occurred here and there. Modified: pypy/trunk/pypy/annotation/builtin.py ============================================================================== --- pypy/trunk/pypy/annotation/builtin.py (original) +++ pypy/trunk/pypy/annotation/builtin.py Tue Jun 8 23:42:50 2010 @@ -346,7 +346,7 @@ assert s_type.is_constant() return SomePtr(s_type.const) -def llmemory_cast_adr_to_int(s): +def llmemory_cast_adr_to_int(s, s_mode=None): return SomeInteger() # xxx def llmemory_cast_int_to_adr(s): Modified: pypy/trunk/pypy/annotation/description.py ============================================================================== --- pypy/trunk/pypy/annotation/description.py (original) +++ pypy/trunk/pypy/annotation/description.py Tue Jun 8 23:42:50 2010 @@ -539,9 +539,18 @@ try: args.fixedunpack(0) except ValueError: - raise Exception("default __init__ takes no argument" " (class %s)" % (self.name,)) + elif self.pyobj is Exception: + # check explicitly against "raise Exception, x" where x + # is a low-level exception pointer + try: + [s_arg] = args.fixedunpack(1) + except ValueError: + pass + else: + from pypy.annotation.model import SomePtr + assert not isinstance(s_arg, SomePtr) else: # call the constructor args = args.prepend(s_instance) Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Tue Jun 8 23:42:50 2010 @@ -3321,6 +3321,17 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + # + def f(): + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise Exception, lle + # ^^^ instead, must cast back from a base ptr to an instance + a = self.RPythonAnnotator() + py.test.raises(AssertionError, a.build_types, f, []) + def test_unicode_decode_error(self): def f(): try: Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py Tue Jun 8 23:42:50 2010 @@ -7,9 +7,10 @@ import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel -from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, +from pypy.jit.metainterp.history import (ConstInt, ConstPtr, BoxInt, BoxPtr, BoxObj, BoxFloat, REF, INT, FLOAT) +from pypy.jit.codewriter import heaptracker from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport @@ -73,12 +74,12 @@ 'int_eq' : (('int', 'int'), 'bool'), 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), + 'int_is_zero' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), - 'bool_not' : (('bool',), 'bool'), 'uint_add' : (('int', 'int'), 'int'), 'uint_sub' : (('int', 'int'), 'int'), 'uint_mul' : (('int', 'int'), 'int'), @@ -103,7 +104,6 @@ 'float_ge' : (('float', 'float'), 'bool'), 'float_neg' : (('float',), 'float'), 'float_abs' : (('float',), 'float'), - 'float_is_true' : (('float',), 'bool'), 'cast_float_to_int':(('float',), 'int'), 'cast_int_to_float':(('int',), 'float'), 'same_as' : (('int',), 'int'), # could also be ptr=>ptr @@ -155,16 +155,6 @@ 'force_token' : ((), 'int'), 'call_may_force' : (('int', 'varargs'), 'intorptr'), 'guard_not_forced': ((), None), - 'virtual_ref' : (('ref', 'int'), 'ref'), - 'virtual_ref_finish': (('ref', 'ref'), None), - #'getitem' : (('void', 'ref', 'int'), 'int'), - #'setitem' : (('void', 'ref', 'int', 'int'), None), - #'newlist' : (('void', 'varargs'), 'ref'), - #'append' : (('void', 'ref', 'int'), None), - #'insert' : (('void', 'ref', 'int', 'int'), None), - #'pop' : (('void', 'ref',), 'int'), - #'len' : (('void', 'ref',), 'int'), - #'listnonzero' : (('void', 'ref',), 'int'), } # ____________________________________________________________ @@ -231,19 +221,19 @@ else: return repr(x) -def repr_list(lst, types, memocast): +def repr_list(lst, types): res_l = [] if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, memocast)) + res_l.append('(%s)' % repr1(elem, tp)) else: - res_l.append(repr1(elem, tp, memocast)) + res_l.append(repr1(elem, tp)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, memocast): +def repr1(x, tp): if tp == "intorptr": TYPE = lltype.typeOf(x) if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': @@ -259,7 +249,7 @@ return '(* None)' if isinstance(x, int): # XXX normalize? - ptr = str(cast_int_to_adr(memocast, x)) + ptr = str(llmemory.cast_int_to_adr(x)) elif isinstance(ootype.typeOf(x), ootype.OOType): return repr(x) else: @@ -400,10 +390,9 @@ class Frame(object): OPHANDLERS = [None] * (rop._LAST+1) - def __init__(self, memocast, cpu): + def __init__(self, cpu): self.verbose = False self.cpu = cpu - self.memocast = memocast self.opindex = 1 self._forced = False self._may_force = -1 @@ -522,15 +511,14 @@ elif res is NotImplemented: resdata = '*fail*' else: - resdata = '-> ' + repr1(res, restype, self.memocast) + resdata = '-> ' + repr1(res, restype) # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), + log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes), resdata)) return res def as_int(self, x): - return cast_to_int(x, self.memocast) + return cast_to_int(x) def as_ptr(self, x): return cast_to_ptr(x) @@ -554,34 +542,36 @@ try: op = getattr(cls, 'op_' + opname.lower()) # op_guard_true etc. except AttributeError: - name = 'do_' + opname.lower() try: - impl = globals()[name] # do_arraylen_gc etc. + impl = globals()['do_' + opname.lower()] # do_arraylen_gc etc. def op(self, descr, *args): - return impl(descr, *args) - # + if descr is None: + return impl(*args) + else: + return impl(descr, *args) except KeyError: - from pypy.jit.backend.llgraph import llimpl - impl = getattr(executor, name) # do_int_add etc. - def _op_default_implementation(self, descr, *args): - # for all operations implemented in execute.py - boxedargs = [] - for x in args: - if type(x) is int: - boxedargs.append(BoxInt(x)) - elif type(x) is float: - boxedargs.append(BoxFloat(x)) - elif isinstance(ootype.typeOf(x), ootype.OOType): - boxedargs.append(BoxObj(ootype.cast_to_object(x))) - else: - boxedargs.append(BoxPtr(x)) - # xxx this passes the 'llimpl' module as the CPU argument - resbox = impl(llimpl, *boxedargs) - return getattr(resbox, 'value', None) - op = _op_default_implementation - # + op = cls._make_impl_from_blackhole_interp(opname) cls.OPHANDLERS[opnum] = op + @classmethod + def _make_impl_from_blackhole_interp(cls, opname): + from pypy.jit.metainterp.blackhole import BlackholeInterpreter + name = 'bhimpl_' + opname.lower() + func = BlackholeInterpreter.__dict__[name] + for argtype in func.argtypes: + assert argtype in ('i', 'r', 'f') + # + def _op_default_implementation(self, descr, *args): + # for all operations implemented in the blackhole interpreter + return func(*args) + # + return _op_default_implementation + + def op_debug_merge_point(self, _, value): + from pypy.jit.metainterp.warmspot import get_stats + loc = ConstPtr(value)._get_str() + get_stats().add_merge_point_location(loc) + def op_guard_true(self, _, value): if not value: raise GuardFailed @@ -596,7 +586,7 @@ def op_guard_class(self, _, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_class), + llmemory.cast_int_to_adr(expected_class), rclass.CLASSTYPE) if value.typeptr != expected_class: raise GuardFailed @@ -630,7 +620,7 @@ def _cast_exception(self, exception): return llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, exception), + llmemory.cast_int_to_adr(exception), rclass.CLASSTYPE) def _issubclass(self, cls1, cls2): @@ -696,7 +686,7 @@ if arraydescr.typeinfo == REF: return do_getarrayitem_gc_ptr(array, index) elif arraydescr.typeinfo == INT: - return do_getarrayitem_gc_int(array, index, self.memocast) + return do_getarrayitem_gc_int(array, index) elif arraydescr.typeinfo == FLOAT: return do_getarrayitem_gc_float(array, index) else: @@ -708,7 +698,7 @@ if fielddescr.typeinfo == REF: return do_getfield_gc_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_gc_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: return do_getfield_gc_float(struct, fielddescr.ofs) else: @@ -718,11 +708,11 @@ def op_getfield_raw(self, fielddescr, struct): if fielddescr.typeinfo == REF: - return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: - return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_float(struct, fielddescr.ofs) else: raise NotImplementedError @@ -733,17 +723,17 @@ def op_new_with_vtable(self, descr, vtable): assert descr is None - size = get_class_size(self.memocast, vtable) - result = do_new(size) + descr = heaptracker.vtable2descr(self.cpu, vtable) + result = do_new(descr.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) - value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) + value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr.typeinfo == REF: do_setarrayitem_gc_ptr(array, index, newvalue) elif arraydescr.typeinfo == INT: - do_setarrayitem_gc_int(array, index, newvalue, self.memocast) + do_setarrayitem_gc_int(array, index, newvalue) elif arraydescr.typeinfo == FLOAT: do_setarrayitem_gc_float(array, index, newvalue) else: @@ -753,8 +743,7 @@ if fielddescr.typeinfo == REF: do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_gc_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: do_setfield_gc_float(struct, fielddescr.ofs, newvalue) else: @@ -762,30 +751,41 @@ def op_setfield_raw(self, fielddescr, struct, newvalue): if fielddescr.typeinfo == REF: - do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: - do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_float(struct, fielddescr.ofs, newvalue) else: raise NotImplementedError def op_call(self, calldescr, func, *args): - _call_args[:] = args - if calldescr.typeinfo == 'v': - err_result = None - elif calldescr.typeinfo == REF: - err_result = lltype.nullptr(llmemory.GCREF.TO) - elif calldescr.typeinfo == INT: - err_result = 0 - elif calldescr.typeinfo == FLOAT: - err_result = 0.0 - else: - raise NotImplementedError - return _do_call_common(func, self.memocast, err_result) + global _last_exception + assert _last_exception is None, "exception left behind" + assert _call_args_i == _call_args_r == _call_args_f == [] + args_in_order = [] + for x in args: + T = lltype.typeOf(x) + if T is lltype.Signed: + args_in_order.append('i') + _call_args_i.append(x) + elif T == llmemory.GCREF: + args_in_order.append('r') + _call_args_r.append(x) + elif T is lltype.Float: + args_in_order.append('f') + _call_args_f.append(x) + else: + raise TypeError(x) + try: + return _do_call_common(func, args_in_order) + except LLException, lle: + _last_exception = lle + d = {'v': None, + REF: lltype.nullptr(llmemory.GCREF.TO), + INT: 0, + FLOAT: 0.0} + return d[calldescr.typeinfo] op_call_pure = op_call @@ -801,7 +801,7 @@ return do_new_array(arraydescr.ofs, count) def op_cast_ptr_to_int(self, descr, ptr): - return cast_to_int(ptr, self.memocast) + return cast_to_int(ptr) def op_uint_xor(self, descr, arg1, arg2): return arg1 ^ arg2 @@ -859,12 +859,6 @@ if forced: raise GuardFailed - def op_virtual_ref(self, _, virtual, index): - return virtual - - def op_virtual_ref_finish(self, _, vref, virtual): - pass - class OOFrame(Frame): @@ -925,7 +919,7 @@ def op_call(self, calldescr, func, *args): sm = ootype.cast_from_object(calldescr.FUNC, func) - newargs = cast_call_args(calldescr.FUNC.ARGS, args, self.memocast) + newargs = cast_call_args(calldescr.FUNC.ARGS, args) res = call_maybe_on_top_of_llinterp(sm, newargs) if isinstance(calldescr.FUNC.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -937,7 +931,7 @@ METH = descr.METH obj = ootype.cast_from_object(descr.SELFTYPE, obj) meth = getattr(obj, descr.methname) - newargs = cast_call_args(METH.ARGS, args, self.memocast) + newargs = cast_call_args(METH.ARGS, args) res = call_maybe_on_top_of_llinterp(meth, newargs) if isinstance(METH.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -973,27 +967,27 @@ # ____________________________________________________________ -def cast_to_int(x, memocast): +def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): - return cast_adr_to_int(memocast, llmemory.cast_ptr_to_adr(x)) + return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return cast_adr_to_int(memocast, x) + return heaptracker.adr2int(x) return lltype.cast_primitive(lltype.Signed, x) -def cast_from_int(TYPE, x, memocast): +def cast_from_int(TYPE, x): if isinstance(TYPE, lltype.Ptr): - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) elif TYPE == llmemory.Address: - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) assert lltype.typeOf(x) == llmemory.Address return x else: if lltype.typeOf(x) == llmemory.Address: - x = cast_adr_to_int(memocast, x) + x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x) def cast_to_ptr(x): @@ -1013,11 +1007,11 @@ return x -def new_frame(memocast, is_oo, cpu): +def new_frame(is_oo, cpu): if is_oo: - frame = OOFrame(memocast, cpu) + frame = OOFrame(cpu) else: - frame = Frame(memocast, cpu) + frame = Frame(cpu) return _to_opaque(frame) _future_values = [] @@ -1067,69 +1061,68 @@ def frame_int_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Signed + return x def frame_float_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Float + return x def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - result = frame.fail_args[num] - frame.fail_args[num] = None - return result + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) == llmemory.GCREF + return x -_last_exception = None +def frame_get_value_count(frame): + frame = _from_opaque(frame) + return len(frame.fail_args) -def get_exception(): - if _last_exception: - return llmemory.cast_ptr_to_adr(_last_exception.args[0]) - else: - return llmemory.NULL +def frame_clear_latest_values(frame, count): + frame = _from_opaque(frame) + assert count == len(frame.fail_args) + del frame.fail_args -def get_exc_value(): - if _last_exception: - return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) - else: - return lltype.nullptr(llmemory.GCREF.TO) +_last_exception = None -def clear_exception(): +def grab_exc_value(): global _last_exception - _last_exception = None + if _last_exception is not None: + result = _last_exception.args[1] + _last_exception = None + return lltype.cast_opaque_ptr(llmemory.GCREF, result) + else: + return lltype.nullptr(llmemory.GCREF.TO) -_pseudo_exceptions = {} +##_pseudo_exceptions = {} -def _get_error(Class): - if _llinterp.typer is not None: - llframe = _llinterp.frame_class(None, None, _llinterp) - try: - llframe.make_llexception(Class()) - except LLException, e: - return e - else: - assert 0, "should have raised" - else: - # for tests, a random emulated ll_inst will do - if Class not in _pseudo_exceptions: - ll_inst = lltype.malloc(rclass.OBJECT, zero=True) - ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, - immortal=True) - _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) - return _pseudo_exceptions[Class] - -def get_overflow_error(): - return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0]) - -def get_overflow_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(OverflowError).args[1]) - -def get_zero_division_error(): - return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0]) - -def get_zero_division_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(ZeroDivisionError).args[1]) +##def _get_error(Class): +## if _llinterp.typer is not None: +## llframe = _llinterp.frame_class(None, None, _llinterp) +## try: +## llframe.make_llexception(Class()) +## except LLException, e: +## return e +## else: +## assert 0, "should have raised" +## else: +## # for tests, a random emulated ll_inst will do +## if Class not in _pseudo_exceptions: +## ll_inst = lltype.malloc(rclass.OBJECT, zero=True) +## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, +## immortal=True) +## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) +## return _pseudo_exceptions[Class] + +##def get_overflow_error_value(): +## return lltype.cast_opaque_ptr(llmemory.GCREF, +## _get_error(OverflowError).args[1]) def force(opaque_frame): frame = _from_opaque(opaque_frame) @@ -1151,40 +1144,30 @@ def get_frame_forced_token(opaque_frame): return llmemory.cast_ptr_to_adr(opaque_frame) -class MemoCast(object): - def __init__(self): - self.addresses = [llmemory.NULL] - self.rev_cache = {} - self.vtable_to_size = {} - -def new_memo_cast(): - memocast = MemoCast() - return _to_opaque(memocast) - -def cast_adr_to_int(memocast, adr): - # xxx slow - assert lltype.typeOf(adr) == llmemory.Address - memocast = _from_opaque(memocast) - addresses = memocast.addresses - for i in xrange(len(addresses)-1, -1, -1): - if addresses[i] == adr: - return i - i = len(addresses) - addresses.append(adr) - return i - -def cast_int_to_adr(memocast, int): - memocast = _from_opaque(memocast) - assert 0 <= int < len(memocast.addresses) - return memocast.addresses[int] - -def get_class_size(memocast, vtable): - memocast = _from_opaque(memocast) - return memocast.vtable_to_size[vtable] - -def set_class_size(memocast, vtable, size): - memocast = _from_opaque(memocast) - memocast.vtable_to_size[vtable] = size +##def cast_adr_to_int(memocast, adr): +## # xxx slow +## assert lltype.typeOf(adr) == llmemory.Address +## memocast = _from_opaque(memocast) +## addresses = memocast.addresses +## for i in xrange(len(addresses)-1, -1, -1): +## if addresses[i] == adr: +## return i +## i = len(addresses) +## addresses.append(adr) +## return i + +##def cast_int_to_adr(memocast, int): +## memocast = _from_opaque(memocast) +## assert 0 <= int < len(memocast.addresses) +## return memocast.addresses[int] + +##def get_class_size(memocast, vtable): +## memocast = _from_opaque(memocast) +## return memocast.vtable_to_size[vtable] + +##def set_class_size(memocast, vtable, size): +## memocast = _from_opaque(memocast) +## memocast.vtable_to_size[vtable] = size class GuardFailed(Exception): pass @@ -1192,29 +1175,32 @@ # ____________________________________________________________ +def do_same_as(x): + return x + def do_arraylen_gc(arraydescr, array): array = array._obj.container return array.getlength() -def do_strlen(_, string): +def do_strlen(string): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return len(str.chars) -def do_strgetitem(_, string, index): +def do_strgetitem(string, index): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) -def do_unicodelen(_, string): +def do_unicodelen(string): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return len(uni.chars) -def do_unicodegetitem(_, string, index): +def do_unicodegetitem(string, index): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return ord(uni.chars[index]) -def do_getarrayitem_gc_int(array, index, memocast): +def do_getarrayitem_gc_int(array, index): array = array._obj.container - return cast_to_int(array.getitem(index), memocast) + return cast_to_int(array.getitem(index)) def do_getarrayitem_gc_float(array, index): array = array._obj.container @@ -1229,8 +1215,8 @@ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_gc_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_gc(struct, fieldnum), memocast) +def do_getfield_gc_int(struct, fieldnum): + return cast_to_int(_getfield_gc(struct, fieldnum)) def do_getfield_gc_float(struct, fieldnum): return cast_to_float(_getfield_gc(struct, fieldnum)) @@ -1238,19 +1224,19 @@ def do_getfield_gc_ptr(struct, fieldnum): return cast_to_ptr(_getfield_gc(struct, fieldnum)) -def _getfield_raw(struct, fieldnum, memocast): +def _getfield_raw(struct, fieldnum): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_raw_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast) +def do_getfield_raw_int(struct, fieldnum): + return cast_to_int(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_float(struct, fieldnum, memocast): - return cast_to_float(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_float(struct, fieldnum): + return cast_to_float(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_ptr(struct, fieldnum, memocast): - return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_ptr(struct, fieldnum): + return cast_to_ptr(_getfield_raw(struct, fieldnum)) def do_new(size): TYPE = symbolic.Size2Type[size] @@ -1262,10 +1248,10 @@ x = lltype.malloc(TYPE, count, zero=True) return cast_to_ptr(x) -def do_setarrayitem_gc_int(array, index, newvalue, memocast): +def do_setarrayitem_gc_int(array, index, newvalue): array = array._obj.container ITEMTYPE = lltype.typeOf(array).OF - newvalue = cast_from_int(ITEMTYPE, newvalue, memocast) + newvalue = cast_from_int(ITEMTYPE, newvalue) array.setitem(index, newvalue) def do_setarrayitem_gc_float(array, index, newvalue): @@ -1280,11 +1266,11 @@ newvalue = cast_from_ptr(ITEMTYPE, newvalue) array.setitem(index, newvalue) -def do_setfield_gc_int(struct, fieldnum, newvalue, memocast): +def do_setfield_gc_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) def do_setfield_gc_float(struct, fieldnum, newvalue): @@ -1301,108 +1287,129 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_int(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_float(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_float(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_float(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_ptr(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_newstr(_, length): +def do_newstr(length): x = rstr.mallocstr(length) return cast_to_ptr(x) -def do_newunicode(_, length): +def do_newunicode(length): return cast_to_ptr(rstr.mallocunicode(length)) -def do_strsetitem(_, string, index, newvalue): +def do_strsetitem(string, index, newvalue): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) -def do_unicodesetitem(_, string, index, newvalue): +def do_unicodesetitem(string, index, newvalue): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) uni.chars[index] = unichr(newvalue) # ---------- call ---------- -_call_args = [] +_call_args_i = [] +_call_args_r = [] +_call_args_f = [] def do_call_pushint(x): - _call_args.append(x) - -def do_call_pushfloat(x): - _call_args.append(x) + _call_args_i.append(x) def do_call_pushptr(x): - _call_args.append(x) + _call_args_r.append(x) -def _do_call_common(f, memocast, err_result=None): - global _last_exception - assert _last_exception is None, "exception left behind" - ptr = cast_int_to_adr(memocast, f).ptr +def do_call_pushfloat(x): + _call_args_f.append(x) + +def _do_call_common(f, args_in_order=None): + ptr = llmemory.cast_int_to_adr(f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS - args = cast_call_args(ARGS, _call_args, memocast) - del _call_args[:] + args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f, + args_in_order) + del _call_args_i[:] + del _call_args_r[:] + del _call_args_f[:] assert len(ARGS) == len(args) - try: - if hasattr(ptr._obj, 'graph'): - llinterp = _llinterp # it's a global set here by CPU.__init__() - result = llinterp.eval_graph(ptr._obj.graph, args) - else: - result = ptr._obj._callable(*args) - except LLException, e: - _last_exception = e - result = err_result + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() + result = llinterp.eval_graph(ptr._obj.graph, args) + # ^^^ may raise, in which case we get an LLException + else: + result = ptr._obj._callable(*args) return result -def do_call_void(f, memocast): - _do_call_common(f, memocast) +def do_call_void(f): + _do_call_common(f) -def do_call_int(f, memocast): - x = _do_call_common(f, memocast, 0) - return cast_to_int(x, memocast) +def do_call_int(f): + x = _do_call_common(f) + return cast_to_int(x) -def do_call_float(f, memocast): - x = _do_call_common(f, memocast, 0) +def do_call_float(f): + x = _do_call_common(f) return cast_to_float(x) -def do_call_ptr(f, memocast): - x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO)) +def do_call_ptr(f): + x = _do_call_common(f) return cast_to_ptr(x) -def cast_call_args(ARGS, args, memocast): - argsiter = iter(args) +def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None): + argsiter_i = iter(args_i) + argsiter_r = iter(args_r) + argsiter_f = iter(args_f) + if args_in_order is not None: + orderiter = iter(args_in_order) args = [] for TYPE in ARGS: if TYPE is lltype.Void: x = None else: - x = argsiter.next() if isinstance(TYPE, ootype.OOType): + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = ootype.cast_from_object(TYPE, x) elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = cast_from_ptr(TYPE, x) elif TYPE is lltype.Float: + if args_in_order is not None: + n = orderiter.next() + assert n == 'f' + x = argsiter_f.next() x = cast_from_float(TYPE, x) else: - x = cast_from_int(TYPE, x, memocast) + if args_in_order is not None: + n = orderiter.next() + assert n == 'i' + x = argsiter_i.next() + x = cast_from_int(TYPE, x) args.append(x) - assert list(argsiter) == [] + assert list(argsiter_i) == [] + assert list(argsiter_r) == [] + assert list(argsiter_f) == [] return args @@ -1421,7 +1428,7 @@ result = llinterp.eval_graph(mymethod.graph, myargs) else: result = meth(*args) - except LLException, e: + except XXX-LLException, e: _last_exception = e result = get_err_result_for_type(mymethod._TYPE.RESULT) return result @@ -1474,16 +1481,13 @@ COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame")) -MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[OOFrame] = OOFRAME.TO -_TO_OPAQUE[MemoCast] = MEMOCAST.TO s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) s_Frame = annmodel.SomePtr(FRAME) -s_MemoCast = annmodel.SomePtr(MEMOCAST) setannotation(compile_start, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) @@ -1512,23 +1516,14 @@ setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) setannotation(frame_float_getvalue, annmodel.SomeFloat()) +setannotation(frame_get_value_count, annmodel.SomeInteger()) +setannotation(frame_clear_latest_values, annmodel.s_None) -setannotation(get_exception, annmodel.SomeAddress()) -setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(clear_exception, annmodel.s_None) -setannotation(get_overflow_error, annmodel.SomeAddress()) -setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(get_zero_division_error, annmodel.SomeAddress()) -setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF)) setannotation(force, annmodel.SomeInteger()) setannotation(get_forced_token_frame, s_Frame) setannotation(get_frame_forced_token, annmodel.SomeAddress()) -setannotation(new_memo_cast, s_MemoCast) -setannotation(cast_adr_to_int, annmodel.SomeInteger()) -setannotation(cast_int_to_adr, annmodel.SomeAddress()) -setannotation(set_class_size, annmodel.s_None) - setannotation(do_arraylen_gc, annmodel.SomeInteger()) setannotation(do_strlen, annmodel.SomeInteger()) setannotation(do_strgetitem, annmodel.SomeInteger()) Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/runner.py Tue Jun 8 23:42:50 2010 @@ -15,6 +15,7 @@ from pypy.jit.backend import model from pypy.jit.backend.llgraph import llimpl, symbolic from pypy.jit.metainterp.typesystem import llhelper, oohelper +from pypy.jit.codewriter import heaptracker from pypy.rlib import rgc class MiniStats: @@ -23,11 +24,19 @@ class Descr(history.AbstractDescr): - def __init__(self, ofs, typeinfo, extrainfo=None, name=None): + def __init__(self, ofs, typeinfo, extrainfo=None, name=None, + arg_types=None): self.ofs = ofs self.typeinfo = typeinfo self.extrainfo = extrainfo self.name = name + self.arg_types = arg_types + + def get_arg_types(self): + return self.arg_types + + def get_return_type(self): + return self.typeinfo def get_extra_info(self): return self.extrainfo @@ -51,6 +60,9 @@ def is_array_of_floats(self): return self.typeinfo == FLOAT + def as_vtable_size_descr(self): + return self + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -86,7 +98,6 @@ self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.stats.exec_conditional_jumps = 0 - self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._llinterp = LLInterpreter(self.rtyper) self._future_values = [] @@ -96,22 +107,16 @@ assert self.translate_support_code return False - def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None): - key = (ofs, typeinfo, extrainfo, name) + def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None, + arg_types=None): + key = (ofs, typeinfo, extrainfo, name, arg_types) try: return self._descrs[key] except KeyError: - descr = Descr(ofs, typeinfo, extrainfo, name) + descr = Descr(ofs, typeinfo, extrainfo, name, arg_types) self._descrs[key] = descr return descr - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - for vtable, size in class_sizes.items(): - if not self.is_oo: - size = size.ofs - llimpl.set_class_size(self.memo_cast, vtable, size) - def compile_bridge(self, faildescr, inputargs, operations): c = llimpl.compile_start() self._compile_loop_or_bridge(c, inputargs, operations) @@ -161,8 +166,6 @@ llimpl.compile_add_int_const(c, x.value) elif isinstance(x, self.ts.ConstRef): llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) elif isinstance(x, history.ConstFloat): llimpl.compile_add_float_const(c, x.value) else: @@ -213,7 +216,7 @@ def _execute_token(self, loop_token): compiled_version = loop_token._llgraph_compiled_version - frame = llimpl.new_frame(self.memo_cast, self.is_oo, self) + frame = llimpl.new_frame(self.is_oo, self) # setup the frame llimpl.frame_clear(frame, compiled_version) # run the loop @@ -247,60 +250,22 @@ def get_latest_value_float(self, index): return llimpl.frame_float_getvalue(self.latest_frame, index) + def get_latest_value_count(self): + return llimpl.frame_get_value_count(self.latest_frame) + def get_latest_force_token(self): token = llimpl.get_frame_forced_token(self.latest_frame) - return self.cast_adr_to_int(token) + return heaptracker.adr2int(token) - def make_boxes_from_latest_values(self, faildescr): - inputargs_and_holes = [] - for i in range(len(faildescr._fail_args_types)): - boxtype = faildescr._fail_args_types[i] - if boxtype == history.INT: - box = history.BoxInt(self.get_latest_value_int(i)) - elif boxtype == history.REF: - box = self.ts.BoxRef(self.get_latest_value_ref(i)) - elif boxtype == history.FLOAT: - box = history.BoxFloat(self.get_latest_value_float(i)) - elif boxtype == history.HOLE: - box = None - else: - assert False, "bad box type: num=%d" % ord(boxtype) - inputargs_and_holes.append(box) - return inputargs_and_holes + def clear_latest_values(self, count): + llimpl.frame_clear_latest_values(self.latest_frame, count) # ---------- - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) - - def get_exc_value(self): - return llimpl.get_exc_value() - - def clear_exception(self): - llimpl.clear_exception() - - def get_overflow_error(self): - return (self.cast_adr_to_int(llimpl.get_overflow_error()), - llimpl.get_overflow_error_value()) - - def get_zero_division_error(self): - return (self.cast_adr_to_int(llimpl.get_zero_division_error()), - llimpl.get_zero_division_error_value()) - def sizeof(self, S): assert not isinstance(S, lltype.Ptr) return self.getdescr(symbolic.get_size(S)) - def cast_adr_to_int(self, adr): - return llimpl.cast_adr_to_int(self.memo_cast, adr) - - def cast_int_to_adr(self, int): - return llimpl.cast_int_to_adr(self.memo_cast, int) - - def cast_gcref_to_int(self, gcref): - return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref)) - - class LLtypeCPU(BaseCPU): is_oo = False @@ -316,14 +281,17 @@ return self.getdescr(ofs, token[0], name=fieldname) def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): + arg_types = [] + for ARG in ARGS: + token = history.getkind(ARG) + if token != 'void': + arg_types.append(token[0]) token = history.getkind(RESULT) - return self.getdescr(0, token[0], extrainfo=extrainfo) - - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) + return self.getdescr(0, token[0], extrainfo=extrainfo, + arg_types=''.join(arg_types)) - def get_exc_value(self): - return llimpl.get_exc_value() + def grab_exc_value(self): + return llimpl.grab_exc_value() def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) @@ -334,202 +302,151 @@ # ---------- the backend-dependent operations ---------- - def do_arraylen_gc(self, arraybox, arraydescr): - array = arraybox.getref_base() - return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - - def do_strlen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_strlen(0, string)) - - def do_strgetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_strgetitem(0, string, index)) - - def do_unicodelen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_unicodelen(0, string)) - - def do_unicodegetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_unicodegetitem(0, string, index)) + def bh_strlen(self, string): + return llimpl.do_strlen(string) + + def bh_strgetitem(self, string, index): + return llimpl.do_strgetitem(string, index) + + def bh_unicodelen(self, string): + return llimpl.do_unicodelen(string) + + def bh_unicodegetitem(self, string, index): + return llimpl.do_unicodegetitem(string, index) - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) - elif arraydescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, - self.memo_cast)) - elif arraydescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array, - index)) - else: - raise NotImplementedError + return llimpl.do_getarrayitem_gc_int(array, index) + def bh_getarrayitem_gc_r(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_ptr(array, index) + def bh_getarrayitem_gc_f(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_float(array, index) - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_gc_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, - fielddescr.ofs)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_gc_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_gc_float(struct, - fielddescr.ofs)) - else: - raise NotImplementedError + return llimpl.do_getfield_gc_int(struct, fielddescr.ofs) + def bh_getfield_gc_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_ptr(struct, fielddescr.ofs) + def bh_getfield_gc_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_float(struct, fielddescr.ofs) - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_raw_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_raw_float(struct, - fielddescr.ofs, - self.memo_cast)) - else: - raise NotImplementedError + return llimpl.do_getfield_raw_int(struct, fielddescr.ofs) + def bh_getfield_raw_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_ptr(struct, fielddescr.ofs) + def bh_getfield_raw_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_float(struct, fielddescr.ofs) - def do_new(self, size): - assert isinstance(size, Descr) - return history.BoxPtr(llimpl.do_new(size.ofs)) - - def do_new_with_vtable(self, vtablebox): - vtable = vtablebox.getint() - size = self.class_sizes[vtable] - result = llimpl.do_new(size.ofs) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, - vtable, self.memo_cast) - return history.BoxPtr(result) - - def do_new_array(self, countbox, size): - assert isinstance(size, Descr) - count = countbox.getint() - return history.BoxPtr(llimpl.do_new_array(size.ofs, count)) + def bh_new(self, sizedescr): + assert isinstance(sizedescr, Descr) + return llimpl.do_new(sizedescr.ofs) + + def bh_new_with_vtable(self, sizedescr, vtable): + assert isinstance(sizedescr, Descr) + result = llimpl.do_new(sizedescr.ofs) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, vtable) + return result + + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_new_array(self, arraydescr, length): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) - elif arraydescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setarrayitem_gc_int(array, index, newvalue, - self.memo_cast) - elif arraydescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setarrayitem_gc_float(array, index, newvalue) - else: - raise NotImplementedError + return llimpl.do_new_array(arraydescr.ofs, length) + + def bh_arraylen_gc(self, arraydescr, array): + assert isinstance(arraydescr, Descr) + return llimpl.do_arraylen_gc(arraydescr, array) + + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_int(array, index, newvalue) + + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_float(array, index, newvalue) - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - else: - raise NotImplementedError + llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memo_cast) - else: - raise NotImplementedError + llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue) - def do_same_as(self, box1): - return box1.clonebox() + def bh_newstr(self, length): + return llimpl.do_newstr(length) - def do_newstr(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newstr(0, length)) - - def do_newunicode(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newunicode(0, length)) - - def do_strsetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_strsetitem(0, string, index, newvalue) - - def do_unicodesetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_unicodesetitem(0, string, index, newvalue) + def bh_newunicode(self, length): + return llimpl.do_newunicode(length) - def do_call(self, args, calldescr): - assert isinstance(calldescr, Descr) - func = args[0].getint() - for arg in args[1:]: - if arg.type == REF: - llimpl.do_call_pushptr(arg.getref_base()) - elif arg.type == FLOAT: - llimpl.do_call_pushfloat(arg.getfloat()) - else: - llimpl.do_call_pushint(arg.getint()) - if calldescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) - elif calldescr.typeinfo == INT: - return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) - elif calldescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast)) - elif calldescr.typeinfo == 'v': # void - llimpl.do_call_void(func, self.memo_cast) - else: - raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + llimpl.do_strsetitem(string, index, newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + llimpl.do_unicodesetitem(string, index, newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(INT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_int(func) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(REF, calldescr, args_i, args_r, args_f) + return llimpl.do_call_ptr(func) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(FLOAT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_float(func) + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call('v', calldescr, args_i, args_r, args_f) + llimpl.do_call_void(func) - def do_cast_ptr_to_int(self, ptrbox): - return history.BoxInt(llimpl.cast_to_int(ptrbox.getref_base(), - self.memo_cast)) + def _prepare_call(self, resulttypeinfo, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, Descr) + assert calldescr.typeinfo == resulttypeinfo + if args_i is not None: + for x in args_i: + llimpl.do_call_pushint(x) + if args_r is not None: + for x in args_r: + llimpl.do_call_pushptr(x) + if args_f is not None: + for x in args_f: + llimpl.do_call_pushfloat(x) def force(self, force_token): - token = self.cast_int_to_adr(force_token) + token = llmemory.cast_int_to_adr(force_token) frame = llimpl.get_forced_token_frame(token) fail_index = llimpl.force(frame) self.latest_frame = frame return self.get_fail_descr_from_number(fail_index) -class OOtypeCPU(BaseCPU): +class OOtypeCPU_xxx_disabled(BaseCPU): is_oo = True ts = oohelper @@ -629,7 +546,7 @@ assert isinstance(typedescr, TypeDescr) return typedescr.getarraylength(box1) - def do_call(self, args, descr): + def do_call_XXX(self, args, descr): assert isinstance(descr, StaticMethDescr) funcbox = args[0] argboxes = args[1:] @@ -842,10 +759,3 @@ def __repr__(self): return '' % self.fieldname - - -# ____________________________________________________________ - -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(LLtypeCPU) -pypy.jit.metainterp.executor.make_execute_list(OOtypeCPU) Modified: pypy/trunk/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/test/test_llgraph.py Tue Jun 8 23:42:50 2010 @@ -7,6 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.test.runner_test import LLtypeBackendTest class TestLLTypeLLGraph(LLtypeBackendTest): @@ -18,25 +19,25 @@ def setup_method(self, _): self.cpu = self.cpu_type(None) - def test_cast_adr_to_int_and_back(self): - cpu = self.cpu - X = lltype.Struct('X', ('foo', lltype.Signed)) - x = lltype.malloc(X, immortal=True) - x.foo = 42 - a = llmemory.cast_ptr_to_adr(x) - i = cpu.cast_adr_to_int(a) - assert isinstance(i, int) - a2 = cpu.cast_int_to_adr(i) - assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x - assert cpu.cast_adr_to_int(llmemory.NULL) == 0 - assert cpu.cast_int_to_adr(0) == llmemory.NULL +def test_cast_adr_to_int_and_back(): + X = lltype.Struct('X', ('foo', lltype.Signed)) + x = lltype.malloc(X, immortal=True) + x.foo = 42 + a = llmemory.cast_ptr_to_adr(x) + i = heaptracker.adr2int(a) + assert lltype.typeOf(i) is lltype.Signed + a2 = heaptracker.int2adr(i) + assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x + assert heaptracker.adr2int(llmemory.NULL) == 0 + assert heaptracker.int2adr(0) == llmemory.NULL ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type def test_fielddescr_ootype(): + py.test.skip("ootype tests skipped") from pypy.rpython.ootypesystem import ootype from pypy.jit.backend.llgraph.runner import OOtypeCPU A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) Modified: pypy/trunk/pypy/jit/backend/llsupport/descr.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llsupport/descr.py (original) +++ pypy/trunk/pypy/jit/backend/llsupport/descr.py Tue Jun 8 23:42:50 2010 @@ -1,10 +1,11 @@ import py -from pypy.rpython.lltypesystem import lltype, rffi, llmemory +from pypy.rpython.lltypesystem import lltype, rffi, llmemory, rclass from pypy.jit.backend.llsupport import symbolic, support from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # The point of the class organization in this file is to make instances # as compact as possible. This is done by not storing the field size or @@ -40,6 +41,10 @@ def repr_of_descr(self): return '' % self.size +class SizeDescrWithVTable(SizeDescr): + def as_vtable_size_descr(self): + return self + BaseSizeDescr = SizeDescr def get_size_descr(gccache, STRUCT): @@ -48,7 +53,10 @@ return cache[STRUCT] except KeyError: size = symbolic.get_size(STRUCT, gccache.translate_support_code) - sizedescr = SizeDescr(size) + if heaptracker.has_gcstruct_a_vtable(STRUCT): + sizedescr = SizeDescrWithVTable(size) + else: + sizedescr = SizeDescr(size) gccache.init_size_descr(STRUCT, sizedescr) cache[STRUCT] = sizedescr return sizedescr @@ -179,7 +187,6 @@ # CallDescrs class BaseCallDescr(AbstractDescr): - empty_box = BoxInt(0) _clsname = '' loop_token = None arg_classes = '' # <-- annotation hack @@ -191,35 +198,20 @@ def get_extra_info(self): return self.extrainfo - _returns_a_pointer = False # unless overridden by GcPtrCallDescr - _returns_a_float = False # unless overridden by FloatCallDescr - _returns_a_void = False # unless overridden by VoidCallDescr - - def returns_a_pointer(self): - return self._returns_a_pointer - - def returns_a_float(self): - return self._returns_a_float + def get_arg_types(self): + return self.arg_classes - def returns_a_void(self): - return self._returns_a_void + def get_return_type(self): + return self._return_type def get_result_size(self, translate_support_code): raise NotImplementedError - def get_call_stub(self): - return self.call_stub - def create_call_stub(self, rtyper, RESULT): - def process(no, c): - if c == 'i': - return 'args[%d].getint()' % (no,) - elif c == 'f': - return 'args[%d].getfloat()' % (no,) - elif c == 'r': - return 'args[%d].getref_base()' % (no,) - else: - raise Exception("Unknown type %s for type %s" % (c, TP)) + def process(c): + arg = 'args_%s[%d]' % (c, seen[c]) + seen[c] += 1 + return arg def TYPE(arg): if arg == 'i': @@ -230,21 +222,23 @@ return llmemory.GCREF elif arg == 'v': return lltype.Void - - args = ", ".join([process(i + 1, c) for i, c in - enumerate(self.arg_classes)]) - - if self.returns_a_pointer(): - result = 'history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, res))' - elif self.returns_a_float(): - result = 'history.BoxFloat(res)' - elif self.returns_a_void(): + + seen = {'i': 0, 'r': 0, 'f': 0} + args = ", ".join([process(c) for c in self.arg_classes]) + + if self.get_return_type() == history.INT: + result = 'rffi.cast(lltype.Signed, res)' + elif self.get_return_type() == history.REF: + result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)' + elif self.get_return_type() == history.FLOAT: + result = 'res' + elif self.get_return_type() == history.VOID: result = 'None' else: - result = 'history.BoxInt(rffi.cast(lltype.Signed, res))' + assert 0 source = py.code.Source(""" - def call_stub(args): - fnptr = rffi.cast(lltype.Ptr(FUNC), args[0].getint()) + def call_stub(func, args_i, args_r, args_f): + fnptr = rffi.cast(lltype.Ptr(FUNC), func) res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s) return %(result)s """ % locals()) @@ -255,35 +249,64 @@ exec source.compile() in d self.call_stub = d['call_stub'] + def verify_types(self, args_i, args_r, args_f, return_type): + assert self._return_type == return_type + assert self.arg_classes.count('i') == len(args_i or ()) + assert self.arg_classes.count('r') == len(args_r or ()) + assert self.arg_classes.count('f') == len(args_f or ()) + def repr_of_descr(self): return '<%s>' % self._clsname -class NonGcPtrCallDescr(BaseCallDescr): +class BaseIntCallDescr(BaseCallDescr): + # Base class of the various subclasses of descrs corresponding to + # calls having a return kind of 'int' (including non-gc pointers). + # The inheritance hierarchy is a bit different than with other Descr + # classes because of the 'call_stub' attribute, which is of type + # + # lambda func, args_i, args_r, args_f --> int/ref/float/void + # + # The purpose of BaseIntCallDescr is to be the parent of all classes + # in which 'call_stub' has a return kind of 'int'. + _return_type = history.INT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0) + +class NonGcPtrCallDescr(BaseIntCallDescr): _clsname = 'NonGcPtrCallDescr' - def get_result_size(self, translate_support_code): return symbolic.get_size_of_ptr(translate_support_code) -class GcPtrCallDescr(NonGcPtrCallDescr): - empty_box = BoxPtr(lltype.nullptr(llmemory.GCREF.TO)) +class GcPtrCallDescr(BaseCallDescr): _clsname = 'GcPtrCallDescr' - _returns_a_pointer = True + _return_type = history.REF + call_stub = staticmethod(lambda func, args_i, args_r, args_f: + lltype.nullptr(llmemory.GCREF.TO)) + def get_result_size(self, translate_support_code): + return symbolic.get_size_of_ptr(translate_support_code) + +class FloatCallDescr(BaseCallDescr): + _clsname = 'FloatCallDescr' + _return_type = history.FLOAT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0.0) + def get_result_size(self, translate_support_code): + return symbolic.get_size(lltype.Float, translate_support_code) -class VoidCallDescr(NonGcPtrCallDescr): - empty_box = None +class VoidCallDescr(BaseCallDescr): _clsname = 'VoidCallDescr' - _returns_a_void = True - + _return_type = history.VOID + call_stub = staticmethod(lambda func, args_i, args_r, args_f: None) def get_result_size(self, translate_support_code): return 0 def getCallDescrClass(RESULT): if RESULT is lltype.Void: return VoidCallDescr - return getDescrClass(RESULT, BaseCallDescr, GcPtrCallDescr, + if RESULT is lltype.Float: + return FloatCallDescr + return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr, NonGcPtrCallDescr, 'Call', 'get_result_size', - '_returns_a_float') + Ellipsis) # <= floatattrname should not be used here def get_call_descr(gccache, ARGS, RESULT, extrainfo=None): arg_classes = [] @@ -330,7 +353,6 @@ # if TYPE is lltype.Float: setattr(Descr, floatattrname, True) - Descr.empty_box = BoxFloat(0.0) # _cache[nameprefix, TYPE] = Descr return Descr Modified: pypy/trunk/pypy/jit/backend/llsupport/gc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llsupport/gc.py (original) +++ pypy/trunk/pypy/jit/backend/llsupport/gc.py Tue Jun 8 23:42:50 2010 @@ -170,7 +170,7 @@ # first look in the hashtable, using an inexact hash (fails after # the object moves) addr = llmemory.cast_ptr_to_adr(gcref) - hash = llmemory.cast_adr_to_int(addr) + hash = llmemory.cast_adr_to_int(addr, "forced") hash -= hash >> self.HASHTABLE_BITS hash &= self.HASHTABLE_SIZE - 1 addr_ref = self.hashtable[hash] Modified: pypy/trunk/pypy/jit/backend/llsupport/llmodel.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llsupport/llmodel.py (original) +++ pypy/trunk/pypy/jit/backend/llsupport/llmodel.py Tue Jun 8 23:42:50 2010 @@ -6,16 +6,19 @@ from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\ BoxFloat +from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.model import AbstractCPU 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, BaseSizeDescr from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr -from pypy.jit.backend.llsupport.descr import get_call_descr, BaseCallDescr +from pypy.jit.backend.llsupport.descr import get_call_descr +from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr +from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr from pypy.rpython.annlowlevel import cast_instance_to_base_ptr -empty_int_box = BoxInt(0) class AbstractLLCPU(AbstractCPU): from pypy.jit.metainterp.typesystem import llhelper as ts @@ -47,7 +50,7 @@ self._setup_exception_handling_translated() else: self._setup_exception_handling_untranslated() - self.clear_exception() + self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) self.setup() if translate_support_code: self._setup_on_leave_jitted_translated() @@ -57,9 +60,6 @@ def setup(self): pass - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case bk = self.rtyper.annotator.bookkeeper @@ -104,12 +104,10 @@ def save_exception(): # copy from _exception_emulator to the real attributes on self - tp_i = _exception_emulator[0] - v_i = _exception_emulator[1] + v_i = _exception_emulator[1] _exception_emulator[0] = 0 _exception_emulator[1] = 0 - self.saved_exception = tp_i - self.saved_exc_value = self._cast_int_to_gcref(v_i) + self.saved_exc_value = rffi.cast(llmemory.GCREF, v_i) self.pos_exception = pos_exception self.pos_exc_value = pos_exc_value @@ -120,15 +118,14 @@ def pos_exception(): addr = llop.get_exception_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def save_exception(): addr = llop.get_exception_addr(llmemory.Address) - exception = rffi.cast(lltype.Signed, addr.address[0]) addr.address[0] = llmemory.NULL addr = llop.get_exc_value_addr(llmemory.Address) exc_value = rffi.cast(llmemory.GCREF, addr.address[0]) @@ -136,7 +133,6 @@ # from now on, the state is again consistent -- no more RPython # exception is set. The following code produces a write barrier # in the assignment to self.saved_exc_value, as needed. - self.saved_exception = exception self.saved_exc_value = exc_value self.pos_exception = pos_exception @@ -174,16 +170,10 @@ f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc) return rffi.cast(lltype.Signed, f) - def get_exception(self): - return self.saved_exception - - def get_exc_value(self): - return self.saved_exc_value - - def clear_exception(self): - self.saved_exception = 0 + def grab_exc_value(self): + exc = self.saved_exc_value self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) - + return exc # ------------------- helpers and descriptions -------------------- @@ -213,24 +203,30 @@ def unpack_fielddescr(self, fielddescr): assert isinstance(fielddescr, BaseFieldDescr) + return fielddescr.offset + unpack_fielddescr._always_inline_ = True + + def unpack_fielddescr_size(self, fielddescr): + assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset size = fielddescr.get_field_size(self.translate_support_code) - ptr = fielddescr.is_pointer_field() - float = fielddescr.is_float_field() - return ofs, size, ptr, float - unpack_fielddescr._always_inline_ = True + return ofs, size + unpack_fielddescr_size._always_inline_ = True def arraydescrof(self, A): return get_array_descr(self.gc_ll_descr, A) def unpack_arraydescr(self, arraydescr): assert isinstance(arraydescr, BaseArrayDescr) + return arraydescr.get_base_size(self.translate_support_code) + unpack_arraydescr._always_inline_ = True + + def unpack_arraydescr_size(self, arraydescr): + assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_base_size(self.translate_support_code) size = arraydescr.get_item_size(self.translate_support_code) - ptr = arraydescr.is_array_of_pointers() - float = arraydescr.is_array_of_floats() - return ofs, size, ptr, float - unpack_arraydescr._always_inline_ = True + return ofs, size + unpack_arraydescr_size._always_inline_ = True def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo) @@ -249,254 +245,222 @@ # ____________________________________________________________ - def do_arraylen_gc(self, arraybox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_ofs_length(self.translate_support_code) - gcref = arraybox.getref_base() - length = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] - return BoxInt(length) - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) + return rffi.cast(rffi.CArrayPtr(lltype.Signed), array)[ofs/WORD] + + def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex): + ofs, size = self.unpack_arraydescr_size(arraydescr) # --- start of GC unsafe code (no GC operation!) --- items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - pval = self._cast_int_to_gcref(items[itemindex]) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - fval = items[itemindex] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: items = rffi.cast(rffi.CArrayPtr(TYPE), items) val = items[itemindex] # --- end of GC unsafe code --- - return BoxInt(rffi.cast(lltype.Signed, val)) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_setarrayitem_gc(self, arraybox, indexbox, vbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) - # - if ptr: - vboxptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, vboxptr) - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - items[itemindex] = self.cast_gcref_to_int(vboxptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - items[itemindex] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def bh_getarrayitem_gc_r(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + pval = self._cast_int_to_gcref(items[itemindex]) + # --- end of GC unsafe code --- + return pval + + def bh_getarrayitem_gc_f(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + fval = items[itemindex] + # --- end of GC unsafe code --- + return fval + + def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue): + ofs, size = self.unpack_arraydescr_size(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) items = rffi.cast(rffi.CArrayPtr(TYPE), items) - items[itemindex] = rffi.cast(TYPE, val) + items[itemindex] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def _new_do_len(TP): - def do_strlen(self, stringbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(TP, - self.translate_support_code) - gcref = stringbox.getref_base() - v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] - return BoxInt(v) - return do_strlen - - do_strlen = _new_do_len(rstr.STR) - do_unicodelen = _new_do_len(rstr.UNICODE) - - def do_strgetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] - return BoxInt(ord(v)) - - def do_unicodegetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - basesize = basesize // itemsize - v = rffi.cast(rffi.CArrayPtr(lltype.UniChar), gcref)[basesize + i] - return BoxInt(ord(v)) + def bh_setarrayitem_gc_r(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + self.gc_ll_descr.do_write_barrier(gcref, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + items[itemindex] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- + + def bh_setarrayitem_gc_f(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + items[itemindex] = newvalue + # --- end of GC unsafe code --- + + def bh_strlen(self, string): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return len(s.chars) + + def bh_unicodelen(self, string): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return len(u.chars) + + def bh_strgetitem(self, string, index): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return ord(s.chars[index]) + + def bh_unicodegetitem(self, string, index): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return ord(u.chars[index]) @specialize.argtype(1) - def _base_do_getfield(self, gcref, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) + def _base_do_getfield_i(self, struct, fielddescr): + ofs, size = self.unpack_fielddescr_size(fielddescr) # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), field)[0] - pval = self._cast_int_to_gcref(pval) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - fval = rffi.cast(rffi.CArrayPtr(lltype.Float), field)[0] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - val = rffi.cast(rffi.CArrayPtr(TYPE), field)[0] + val = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)[0] # --- end of GC unsafe code --- - val = rffi.cast(lltype.Signed, val) - return BoxInt(val) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_getfield_gc(self, structbox, fielddescr): - gcref = structbox.getref_base() - return self._base_do_getfield(gcref, fielddescr) + @specialize.argtype(1) + def _base_do_getfield_r(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0] + pval = self._cast_int_to_gcref(pval) + # --- end of GC unsafe code --- + return pval - def do_getfield_raw(self, structbox, fielddescr): - return self._base_do_getfield(structbox.getint(), fielddescr) + @specialize.argtype(1) + def _base_do_getfield_f(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fval = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr)[0] + # --- end of GC unsafe code --- + return fval + + bh_getfield_gc_i = _base_do_getfield_i + bh_getfield_gc_r = _base_do_getfield_r + bh_getfield_gc_f = _base_do_getfield_f + bh_getfield_raw_i = _base_do_getfield_i + bh_getfield_raw_r = _base_do_getfield_r + bh_getfield_raw_f = _base_do_getfield_f @specialize.argtype(1) - def _base_do_setfield(self, gcref, vbox, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) - # - if ptr: - assert lltype.typeOf(gcref) is not lltype.Signed, ( - "can't handle write barriers for setfield_raw") - ptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, ptr) - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Signed), field) - field[0] = self.cast_gcref_to_int(ptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Float), field) - field[0] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def _base_do_setfield_i(self, struct, fielddescr, newvalue): + ofs, size = self.unpack_fielddescr_size(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(TYPE), field) - field[0] = rffi.cast(TYPE, val) + fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr) + fieldptr[0] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def do_setfield_gc(self, structbox, vbox, fielddescr): - gcref = structbox.getref_base() - self._base_do_setfield(gcref, vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_r(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + assert lltype.typeOf(struct) is not lltype.Signed, ( + "can't handle write barriers for setfield_raw") + self.gc_ll_descr.do_write_barrier(struct, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr) + fieldptr[0] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- - def do_setfield_raw(self, structbox, vbox, fielddescr): - self._base_do_setfield(structbox.getint(), vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_f(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr) + fieldptr[0] = newvalue + # --- end of GC unsafe code --- + + bh_setfield_gc_i = _base_do_setfield_i + bh_setfield_gc_r = _base_do_setfield_r + bh_setfield_gc_f = _base_do_setfield_f + bh_setfield_raw_i = _base_do_setfield_i + bh_setfield_raw_r = _base_do_setfield_r + bh_setfield_raw_f = _base_do_setfield_f - def do_new(self, sizedescr): - res = self.gc_ll_descr.gc_malloc(sizedescr) - return BoxPtr(res) + def bh_new(self, sizedescr): + return self.gc_ll_descr.gc_malloc(sizedescr) - def do_new_with_vtable(self, classbox): - classint = classbox.getint() - descrsize = self.class_sizes[classint] - res = self.gc_ll_descr.gc_malloc(descrsize) + def bh_new_with_vtable(self, sizedescr, vtable): + res = self.gc_ll_descr.gc_malloc(sizedescr) if self.vtable_offset is not None: as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res) - as_array[self.vtable_offset/WORD] = classint - return BoxPtr(res) + as_array[self.vtable_offset/WORD] = vtable + return res - def do_new_array(self, countbox, arraydescr): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem) - return BoxPtr(res) - - def do_newstr(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_str(num_elem) - return BoxPtr(res) - - def do_newunicode(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_unicode(num_elem) - return BoxPtr(res) - - def do_strsetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) - - def do_unicodesetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - basesize = basesize // itemsize - rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v) - - def do_call(self, args, calldescr): - assert isinstance(calldescr, BaseCallDescr) - assert len(args) == 1 + len(calldescr.arg_classes) + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) + + def bh_new_array(self, arraydescr, length): + return self.gc_ll_descr.gc_malloc_array(arraydescr, length) + + def bh_newstr(self, length): + return self.gc_ll_descr.gc_malloc_str(length) + + def bh_newunicode(self, length): + return self.gc_ll_descr.gc_malloc_unicode(length) + + def bh_strsetitem(self, string, index, newvalue): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + s.chars[index] = chr(newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + u.chars[index] = unichr(newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, BaseIntCallDescr) if not we_are_translated(): - assert (list(calldescr.arg_classes) == - [arg.type for arg in args[1:]]) - callstub = calldescr.get_call_stub() - try: - return callstub(args) - except Exception, e: - if not we_are_translated(): - if not type(e) is LLException: - raise - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - e.args[1]) - self.saved_exception = rffi.cast(lltype.Signed, e.args[0]) - else: - ptr = cast_instance_to_base_ptr(e) - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - ptr) - self.saved_exception = rffi.cast(lltype.Signed, ptr.typeptr) - return calldescr.empty_box - - def do_cast_ptr_to_int(self, ptrbox): - return BoxInt(self.cast_gcref_to_int(ptrbox.getref_base())) + calldescr.verify_types(args_i, args_r, args_f, history.INT) + return calldescr.call_stub(func, args_i, args_r, args_f) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, GcPtrCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.REF) + return calldescr.call_stub(func, args_i, args_r, args_f) -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, FloatCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.FLOAT) + return calldescr.call_stub(func, args_i, args_r, args_f) + + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, VoidCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.VOID) + return calldescr.call_stub(func, args_i, args_r, args_f) Modified: pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py (original) +++ pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py Tue Jun 8 23:42:50 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp import history def test_get_size_descr(): c0 = GcCache(False) @@ -145,33 +146,29 @@ c0 = GcCache(False) descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char) assert descr1.get_result_size(False) == rffi.sizeof(lltype.Char) - assert not descr1.returns_a_pointer() - assert not descr1.returns_a_float() + assert descr1.get_return_type() == history.INT assert descr1.arg_classes == "ii" - assert isinstance(descr1.empty_box, BoxInt) # T = lltype.GcStruct('T') descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T)) assert descr2.get_result_size(False) == rffi.sizeof(lltype.Ptr(T)) - assert descr2.returns_a_pointer() - assert not descr2.returns_a_float() + assert descr2.get_return_type() == history.REF assert descr2.arg_classes == "r" - assert isinstance(descr2.empty_box, BoxPtr) # U = lltype.GcStruct('U', ('x', lltype.Signed)) assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U)) # V = lltype.Struct('V', ('x', lltype.Signed)) - assert isinstance(get_call_descr(c0, [], lltype.Ptr(V)).empty_box, BoxInt) + assert (get_call_descr(c0, [], lltype.Ptr(V)).get_return_type() == + history.INT) # - assert get_call_descr(c0, [], lltype.Void).empty_box is None + assert (get_call_descr(c0, [], lltype.Void).get_return_type() == + history.VOID) # descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float) assert descr4.get_result_size(False) == rffi.sizeof(lltype.Float) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" - assert isinstance(descr4.empty_box, BoxFloat) def test_get_call_descr_translated(): c1 = GcCache(True) @@ -179,14 +176,12 @@ U = lltype.GcStruct('U', ('x', lltype.Signed)) descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U)) assert isinstance(descr3.get_result_size(True), Symbolic) - assert descr3.returns_a_pointer() - assert not descr3.returns_a_float() + assert descr3.get_return_type() == history.REF assert descr3.arg_classes == "r" # descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float) assert isinstance(descr4.get_result_size(True), Symbolic) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" def test_call_descr_extra_info(): @@ -245,12 +240,11 @@ def f(a, b): return 'c' - call_stub = descr1.get_call_stub() + call_stub = descr1.call_stub fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) - res = call_stub([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxInt(1), BoxInt(2)]) - assert res.getint() == ord('c') + res = call_stub(rffi.cast(lltype.Signed, fnptr), [1, 2], None, None) + assert res == ord('c') ARRAY = lltype.GcArray(lltype.Signed) ARGS = [lltype.Float, lltype.Ptr(ARRAY)] @@ -264,6 +258,6 @@ a = lltype.malloc(ARRAY, 3) opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a) a[0] = 1 - res = descr2.get_call_stub()([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxFloat(3.5), BoxPtr(opaquea)]) - assert res.getfloat() == 4.5 + res = descr2.call_stub(rffi.cast(lltype.Signed, fnptr), + [], [opaquea], [3.5]) + assert res == 4.5 Modified: pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py (original) +++ pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py Tue Jun 8 23:42:50 2010 @@ -291,7 +291,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -303,7 +303,7 @@ assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) - assert operations[1].opnum == rop.OOIS + assert operations[1].opnum == rop.PTR_EQ assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result @@ -324,7 +324,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -336,7 +336,7 @@ finally: rgc.can_move = old_can_move assert len(operations) == 1 - assert operations[0].opnum == rop.OOIS + assert operations[0].opnum == rop.PTR_EQ assert operations[0].args == [v_random_box, ConstPtr(s_gcref)] assert operations[0].result == v_result # check that s_gcref gets added to the list anyway, to make sure Modified: pypy/trunk/pypy/jit/backend/model.py ============================================================================== --- pypy/trunk/pypy/jit/backend/model.py (original) +++ pypy/trunk/pypy/jit/backend/model.py Tue Jun 8 23:42:50 2010 @@ -3,6 +3,7 @@ class AbstractCPU(object): supports_floats = False + _got_exception = None # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None @@ -24,9 +25,6 @@ def get_fail_descr_from_number(self, n): return self.fail_descr_list[n] - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def setup_once(self): """Called once by the front-end when the program starts.""" pass @@ -87,30 +85,27 @@ or from 'args' if it was a FINISH). Returns a ptr or an obj.""" raise NotImplementedError + def get_latest_value_count(self): + """Return how many values are ready to be returned by + get_latest_value_xxx(). Only after a guard failure; not + necessarily correct after a FINISH.""" + raise NotImplementedError + def get_latest_force_token(self): """After a GUARD_NOT_FORCED fails, this function returns the same FORCE_TOKEN result as the one in the just-failed loop.""" raise NotImplementedError - def make_boxes_from_latest_value(self, faildescr): - """Build a list of Boxes (and None for holes) that contains - the current values, as would be returned by calls to - get_latest_value_xxx().""" - raise NotImplementedError - - def get_exception(self): - raise NotImplementedError - - def get_exc_value(self): - raise NotImplementedError - - def clear_exception(self): - raise NotImplementedError - - def get_overflow_error(self): + def clear_latest_values(self, count): + """Clear the latest values (at least the ref ones), so that + they no longer keep objects alive. 'count' is the number of + values -- normally get_latest_value_count().""" raise NotImplementedError - def get_zero_division_error(self): + def grab_exc_value(self): + """Return and clear the exception set by the latest execute_token(), + when it exits due to a failure of a GUARD_EXCEPTION or + GUARD_NO_EXCEPTION. (Returns a GCREF)""" # XXX remove me raise NotImplementedError @staticmethod @@ -118,10 +113,6 @@ raise NotImplementedError @staticmethod - def numof(S): - raise NotImplementedError - - @staticmethod def fielddescrof(S, fieldname): """Return the Descr corresponding to field 'fieldname' on the structure 'S'. It is important that this function (at least) @@ -157,101 +148,87 @@ # lltype specific operations # -------------------------- - - def do_arraylen_gc(self, arraybox, arraydescr): - raise NotImplementedError - def do_strlen(self, stringbox): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): raise NotImplementedError - - def do_strgetitem(self, stringbox, indexbox): + def bh_getarrayitem_gc_r(self, arraydescr, array, index): raise NotImplementedError - - def do_unicodelen(self, stringbox): + def bh_getarrayitem_gc_f(self, arraydescr, array, index): raise NotImplementedError - def do_unicodegetitem(self, stringbox, indexbox): + def bh_getfield_gc_i(self, struct, fielddescr): raise NotImplementedError - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getfield_gc_r(self, struct, fielddescr): + raise NotImplementedError + def bh_getfield_gc_f(self, struct, fielddescr): raise NotImplementedError - def do_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): - return self.do_call([fnptr, sourcebox, destbox, source_startbox, - dest_startbox, lengthbox], calldescr) - - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): raise NotImplementedError - - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_r(self, struct, fielddescr): raise NotImplementedError - - def do_new(self, sizedescr): + def bh_getfield_raw_f(self, struct, fielddescr): raise NotImplementedError - def do_new_with_vtable(self, classbox): + def bh_new(self, sizedescr): + raise NotImplementedError + def bh_new_with_vtable(self, sizedescr, vtable): raise NotImplementedError - - def do_new_array(self, lengthbox, arraydescr): + def bh_new_array(self, arraydescr, length): raise NotImplementedError - - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_newstr(self, length): + raise NotImplementedError + def bh_newunicode(self, length): raise NotImplementedError - def do_setarrayitem_raw(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): raise NotImplementedError - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_classof(self, struct): raise NotImplementedError - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newstr(self, lengthbox): + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newunicode(self, lengthbox): + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): raise NotImplementedError - def do_strsetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_unicodesetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call(self, args, calldescr): + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_assembler(self, args, token): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call_loopinvariant(self, args, calldescr): - return self.do_call(args, calldescr) - - def do_cond_call_gc_wb(self, args, calldescr): + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_cast_ptr_to_int(self, ptrbox): + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_may_force(self, args, calldescr): - return self.do_call(args, calldescr) - - def force(self, force_token): + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - # ootype specific operations - # -------------------------- - - def do_runtimenew(self, classbox): + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - def do_oosend(self, args, descr): + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + raise NotImplementedError + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - def do_instanceof(self, instancebox, typedescr): + def bh_strlen(self, string): + raise NotImplementedError + def bh_strgetitem(self, string, index): + raise NotImplementedError + def bh_unicodelen(self, string): + raise NotImplementedError + def bh_unicodegetitem(self, string, index): + raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + raise NotImplementedError + def bh_unicodesetitem(self, string, index, newvalue): raise NotImplementedError - def typedescr2classbox(self, descr): + def force(self, force_token): raise NotImplementedError Modified: pypy/trunk/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/trunk/pypy/jit/backend/test/runner_test.py (original) +++ pypy/trunk/pypy/jit/backend/test/runner_test.py Tue Jun 8 23:42:50 2010 @@ -13,6 +13,8 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException +from pypy.jit.codewriter import heaptracker + class Runner(object): @@ -236,7 +238,7 @@ res = self.cpu.get_latest_value_int(0) assert res == 20 - def test_make_boxes_from_latest_values(self): + def test_get_latest_value_count(self): i0 = BoxInt() i1 = BoxInt() i2 = BoxInt() @@ -255,12 +257,12 @@ self.cpu.set_future_value_int(0, 2) fail = self.cpu.execute_token(looptoken) assert fail is faildescr1 - boxes = self.cpu.make_boxes_from_latest_values(faildescr1) - assert len(boxes) == 3 - assert boxes[0] is None - assert isinstance(boxes[1], BoxInt) - assert boxes[1].value == 10 - assert boxes[2] is None + + count = self.cpu.get_latest_value_count() + assert count == 3 + assert self.cpu.get_latest_value_int(1) == 10 + assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok + self.cpu.clear_latest_values(3) def test_finish(self): i0 = BoxInt() @@ -375,8 +377,8 @@ looptoken = LoopToken() self.cpu.compile_loop([v1, v2], ops, looptoken) for x, y, z in testcases: - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) fail = self.cpu.execute_token(looptoken) @@ -386,13 +388,13 @@ assert fail.identifier == 2 if z != boom: assert self.cpu.get_latest_value_int(0) == z - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_ovf_operations_reversed(self): self.test_ovf_operations(reversed=True) - def test_do_call(self): + def test_bh_call(self): cpu = self.cpu # def func(c): @@ -400,24 +402,21 @@ FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxInt(ord('A'))], - calldescr) - assert x.value == ord('B') + x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value, + calldescr, [ord('A')], None, None) + assert x == ord('B') if cpu.supports_floats: def func(f, i): - return float(i) + f + return f - float(i) FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed], lltype.Float)) func_ptr = llhelper(FPTR, func) FTP = deref(FPTR) calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxFloat(3.5), BoxInt(42)], - calldescr) - assert x.value == 42 + 3.5 + x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value, + calldescr, + [42], None, [3.5]) + assert x == 3.5 - 42 def test_call(self): @@ -611,31 +610,31 @@ def test_ooops(self): u1_box, U_box = self.alloc_instance(self.U) u2_box, U_box = self.alloc_instance(self.U) - r = self.execute_operation(rop.OOIS, [u1_box, - u1_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, + u1_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [u2_box, - u2_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, + u2_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [u1_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int') assert r.value == 1 # null_box = self.null_instance() - r = self.execute_operation(rop.OOIS, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, + null_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOIS, [u1_box, null_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [null_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, + null_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, null_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [null_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int') assert r.value == 1 def test_array_basic(self): @@ -768,10 +767,10 @@ assert r.value == 153 def test_do_unicode_basic(self): - u_box = self.cpu.do_newunicode(ConstInt(5)) - self.cpu.do_unicodesetitem(u_box, BoxInt(4), BoxInt(123)) - r = self.cpu.do_unicodegetitem(u_box, BoxInt(4)) - assert r.value == 123 + u = self.cpu.bh_newunicode(5) + self.cpu.bh_unicodesetitem(u, 4, 123) + r = self.cpu.bh_unicodegetitem(u, 4) + assert r == 123 def test_unicode_basic(self): u_box = self.alloc_unicode(u"hello\u1234") @@ -808,17 +807,10 @@ assert r.value == 5.5 def test_virtual_ref(self): - # if VIRTUAL_REF reaches the backend, it should just be a SAME_AS - u_box = self.alloc_unicode(u"hello\u1234") - r = self.execute_operation(rop.VIRTUAL_REF, [u_box, ConstInt(2)], - 'ref') - assert r.value == u_box.value + pass # VIRTUAL_REF must not reach the backend nowadays def test_virtual_ref_finish(self): - # if VIRTUAL_REF_FINISH reaches the backend, it is a no-op - self.execute_operation(rop.VIRTUAL_REF_FINISH, - [BoxInt(123), BoxInt(234)], - 'void') + pass # VIRTUAL_REF_FINISH must not reach the backend nowadays def test_jump(self): # this test generates small loops where the JUMP passes many @@ -1082,7 +1074,6 @@ operator.truediv, no_zero_divison yield nan_and_infinity, rop.FLOAT_NEG, operator.neg, all_cases_unary yield nan_and_infinity, rop.FLOAT_ABS, abs, all_cases_unary - yield nan_and_infinity, rop.FLOAT_IS_TRUE, bool, all_cases_unary yield nan_and_infinity, rop.FLOAT_LT, operator.lt, all_cases_binary yield nan_and_infinity, rop.FLOAT_LE, operator.le, all_cases_binary yield nan_and_infinity, rop.FLOAT_EQ, operator.eq, all_cases_binary @@ -1102,7 +1093,7 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): addr = llmemory.cast_ptr_to_adr(func_ptr) - return BoxInt(cpu.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) MY_VTABLE = rclass.OBJECT_VTABLE # for tests only @@ -1134,7 +1125,7 @@ elif T == self.U: t.parent.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) + T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr)) return t_box, T_box def null_instance(self): @@ -1163,23 +1154,26 @@ def test_casts(self): + py.test.skip("xxx fix or kill") from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') x = lltype.malloc(TP) x = lltype.cast_opaque_ptr(llmemory.GCREF, x) res = self.execute_operation(rop.CAST_PTR_TO_INT, [BoxPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) res = self.execute_operation(rop.CAST_PTR_TO_INT, [ConstPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) - r = self.execute_operation(rop.OOIS, [BoxInt(v), BoxInt(v)], 'int') + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) + r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [BoxInt(v), BoxInt(v)], 'int') + r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 0 lltype.free(x, flavor='raw') @@ -1206,7 +1200,7 @@ S = lltype.Struct('S', ('x', lltype.Signed)) s = lltype.malloc(S, flavor='raw') sa = llmemory.cast_ptr_to_adr(s) - s_box = BoxInt(self.cpu.cast_adr_to_int(sa)) + s_box = BoxInt(heaptracker.adr2int(sa)) for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW), (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)): fd = self.cpu.fielddescrof(S, 'x') @@ -1218,7 +1212,9 @@ def test_new_with_vtable(self): cpu = self.cpu t_box, T_box = self.alloc_instance(self.T) - cpu.set_class_sizes({T_box.value: cpu.sizeof(self.T)}) + vtable = llmemory.cast_adr_to_ptr( + llmemory.cast_int_to_adr(T_box.value), heaptracker.VTABLETYPE) + heaptracker.register_known_gctype(cpu, vtable, self.T) r1 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') r2 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') assert r1.value != r2.value @@ -1234,11 +1230,11 @@ s = lltype.cast_opaque_ptr(lltype.Ptr(self.T), r1.value) assert s.parent.chr1 == chr(190) assert s.parent.chr2 == chr(150) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1313 - self.cpu.do_setfield_gc(r1, BoxInt(1333), descrshort) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1333 + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1313 + self.cpu.bh_setfield_gc_i(r1.value, descrshort, 1333) + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1333 r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int', descr=descrshort) assert r.value == 1333 @@ -1305,11 +1301,13 @@ self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 assert self.cpu.get_latest_value_ref(1) == xptr - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) ytp.subclassrange_min = 2 @@ -1327,7 +1325,9 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == yptr + assert not self.cpu.grab_exc_value() # cleared exc_tp = xtp exc_ptr = xptr @@ -1343,11 +1343,13 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == xptr self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_cond_call_gc_wb(self): def func_void(a, b): @@ -1524,108 +1526,92 @@ A = lltype.GcArray(lltype.Char) descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) - x = cpu.do_arraylen_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), - descr_A) - assert x.value == 5 + x = cpu.bh_arraylen_gc(descr_A, + lltype.cast_opaque_ptr(llmemory.GCREF, a)) + assert x == 5 # a[2] = 'Y' - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2), - descr_A) - assert x.value == ord('Y') + x = cpu.bh_getarrayitem_gc_i( + descr_A, lltype.cast_opaque_ptr(llmemory.GCREF, a), 2) + assert x == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3), - descr_B) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 3) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a if self.cpu.supports_floats: C = lltype.GcArray(lltype.Float) c = lltype.malloc(C, 6) c[3] = 3.5 descr_C = cpu.arraydescrof(C) - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(3), - descr_C) - assert isinstance(x, BoxFloat) - assert x.getfloat() == 3.5 - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(4), - BoxFloat(4.5), descr_C) + x = cpu.bh_getarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 3) + assert x == 3.5 + cpu.bh_setarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 4, 4.5) assert c[4] == 4.5 s = rstr.mallocstr(6) - x = cpu.do_strlen( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))) - assert x.value == 6 + x = cpu.bh_strlen(lltype.cast_opaque_ptr(llmemory.GCREF, s)) + assert x == 6 # s.chars[3] = 'X' - x = cpu.do_strgetitem( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)) - assert x.value == ord('X') + x = cpu.bh_strgetitem(lltype.cast_opaque_ptr(llmemory.GCREF, s), 3) + assert x == ord('X') # S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A)), ('z', lltype.Float)) descrfld_x = cpu.fielddescrof(S, 'x') s = lltype.malloc(S) s.x = 'Z' - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_x) - assert x.value == ord('Z') - # - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(ord('4')), - descrfld_x) + x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x) + assert x == ord('Z') + # + cpu.bh_setfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x, + ord('4')) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_y) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a # s.y = lltype.nullptr(A) - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x, - descrfld_y) + cpu.bh_setfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y, x) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char)) #, ('y', lltype.Ptr(A))) descrfld_rx = cpu.fielddescrof(RS, 'x') rs = lltype.malloc(RS, immortal=True) rs.x = '?' - x = cpu.do_getfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + x = cpu.bh_getfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx) - assert x.value == ord('?') + assert x == ord('?') # - cpu.do_setfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(ord('!')), - descrfld_rx) + cpu.bh_setfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), + descrfld_rx, ord('!')) assert rs.x == '!' # if self.cpu.supports_floats: descrfld_z = cpu.fielddescrof(S, 'z') - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxFloat(3.5), - descrfld_z) + cpu.bh_setfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_z, 3.5) assert s.z == 3.5 s.z = 3.2 - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + x = cpu.bh_getfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), descrfld_z) - assert x.getfloat() == 3.2 + assert x == 3.2 ### we don't support in the JIT for now GC pointers ### stored inside non-GC structs. #descrfld_ry = cpu.fielddescrof(RS, 'y') @@ -1643,45 +1629,43 @@ #assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new(descrsize) - assert isinstance(x, BoxPtr) - x.getref(lltype.Ptr(S)) + x = cpu.bh_new(descrsize) + lltype.cast_opaque_ptr(lltype.Ptr(S), x) # type check # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - vtable2_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)) - cpu.set_class_sizes({vtable2_int: descrsize2}) - x = cpu.do_new_with_vtable(ConstInt(vtable2_int)) - assert isinstance(x, BoxPtr) + vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2)) + heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT) + x = cpu.bh_new_with_vtable(descrsize2, vtable2_int) + lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check # well... #assert x.getref(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array(BoxInt(7), arraydescr) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(A))) == 7 - # - cpu.do_setarrayitem_gc( - x, BoxInt(5), BoxInt(ord('*')), descr_A) - assert x.getref(lltype.Ptr(A))[5] == '*' - # - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), - BoxInt(1), x, - descr_B) - assert b[1] == x.getref(lltype.Ptr(A)) - # - x = cpu.do_newstr(BoxInt(5)) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(rstr.STR)).chars) == 5 - # - cpu.do_strsetitem(x, BoxInt(4), BoxInt(ord('/'))) - assert x.getref(lltype.Ptr(rstr.STR)).chars[4] == '/' - # - x = cpu.do_newstr(BoxInt(5)) - y = cpu.do_cast_ptr_to_int(x) - assert isinstance(y, BoxInt) - assert y.value == cpu.cast_gcref_to_int(x.value) + x = cpu.bh_new_array(arraydescr, 7) + array = lltype.cast_opaque_ptr(lltype.Ptr(A), x) + assert len(array) == 7 + # + cpu.bh_setarrayitem_gc_i(descr_A, x, 5, ord('*')) + assert array[5] == '*' + # + cpu.bh_setarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 1, x) + assert b[1] == array + # + x = cpu.bh_newstr(5) + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), x) + assert len(str.chars) == 5 + # + cpu.bh_strsetitem(x, 4, ord('/')) + assert str.chars[4] == '/' + # +## x = cpu.bh_newstr(5) +## y = cpu.bh_cast_ptr_to_int(x) +## z = cpu.bh_cast_ptr_to_int(x) +## y = rffi.get_real_int(y) +## z = rffi.get_real_int(z) +## assert type(y) == type(z) == int and y == z def test_sorting_of_fields(self): S = self.S @@ -1694,7 +1678,7 @@ def test_guards_nongc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) vbox = BoxInt(v) ops = [ (rop.GUARD_NONNULL, vbox, False), @@ -1797,6 +1781,9 @@ malloc = staticmethod(ootype.new) nullptr = staticmethod(ootype.null) + def setup_class(cls): + py.test.skip("ootype tests skipped") + @classmethod def get_funcbox(cls, cpu, func_ptr): return BoxObj(ootype.cast_to_object(func_ptr)) Modified: pypy/trunk/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/trunk/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/trunk/pypy/jit/backend/test/test_ll_random.py Tue Jun 8 23:42:50 2010 @@ -3,8 +3,9 @@ from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr -from pypy.jit.metainterp.history import ConstAddr, BoxPtr, BoxInt +from pypy.jit.metainterp.history import BoxPtr, BoxInt from pypy.jit.metainterp.history import BasicFailDescr +from pypy.jit.codewriter import heaptracker from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask from pypy.rpython.llinterp import LLException @@ -19,13 +20,11 @@ self.runicodes = [] self.structure_types = [] self.structure_types_and_vtables = [] - self.class_sizes_cache = [] def fork(self, cpu, loop, vars): fork = test_random.OperationBuilder.fork(self, cpu, loop, vars) fork.structure_types = self.structure_types fork.structure_types_and_vtables = self.structure_types_and_vtables - fork.class_sizes_cache = self.class_sizes_cache return fork def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): @@ -107,11 +106,7 @@ vtable.name[len(name)] = '\x00' self.structure_types_and_vtables.append((S, vtable)) # - vtable_adr = llmemory.cast_ptr_to_adr(vtable) - vtable_int = self.cpu.cast_adr_to_int(vtable_adr) - descr = self.cpu.sizeof(S) - self.class_sizes_cache.append((vtable_int, descr)) - self.cpu.set_class_sizes(dict(self.class_sizes_cache)) + heaptracker.register_known_gctype(self.cpu, vtable, S) # return S, vtable @@ -186,6 +181,9 @@ # ____________________________________________________________ +def ConstAddr(addr, cpu): + return ConstInt(heaptracker.adr2int(addr)) + class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): ptrvars = [(v, S) for (v, S) in builder.ptrvars @@ -507,8 +505,6 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(), descr=BasicFailDescr()) op.fail_args = fail_subset @@ -525,8 +521,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(), descr=BasicFailDescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) @@ -546,8 +540,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: Modified: pypy/trunk/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/trunk/pypy/jit/backend/test/test_random.py (original) +++ pypy/trunk/pypy/jit/backend/test/test_random.py Tue Jun 8 23:42:50 2010 @@ -4,7 +4,7 @@ from pypy.jit.backend.test import conftest as demo_conftest from pypy.jit.metainterp.history import BasicFailDescr, TreeLoop from pypy.jit.metainterp.history import BoxInt, ConstInt, LoopToken -from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat, Const from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute_nonspec @@ -17,9 +17,14 @@ def __init__(self, subops): self.operations = subops +class FakeMetaInterp(object): + def execute_raised(self, exc, constant=False): + self._got_exc = exc + class OperationBuilder(object): def __init__(self, cpu, loop, vars): self.cpu = cpu + self.fakemetainterp = FakeMetaInterp() self.loop = loop self.intvars = [box for box in vars if isinstance(box, BoxInt)] self.boolvars = [] # subset of self.intvars @@ -40,7 +45,9 @@ return fork def do(self, opnum, argboxes, descr=None): - v_result = execute_nonspec(self.cpu, opnum, argboxes, descr) + self.fakemetainterp._got_exc = None + v_result = execute_nonspec(self.cpu, self.fakemetainterp, + opnum, argboxes, descr) if isinstance(v_result, Const): v_result = v_result.clonebox() self.loop.operations.append(ResOperation(opnum, argboxes, v_result, @@ -56,11 +63,14 @@ if S == S2 and not (isinstance(v, ConstPtr) and isinstance(v2, ConstPtr)): if r.random() < 0.5: - return self.do(rop.OOIS, [v, v2]) + return self.do(rop.PTR_EQ, [v, v2]) else: - return self.do(rop.OOISNOT, [v, v2]) + return self.do(rop.PTR_NE, [v, v2]) v = r.choice(self.intvars) - return self.do(rop.INT_IS_TRUE, [v]) + if r.random() < 0.7: + return self.do(rop.INT_IS_TRUE, [v]) + else: + return self.do(rop.INT_IS_ZERO, [v]) def subset_of_intvars(self, r): subset = [] @@ -79,16 +89,16 @@ for v in op.args: if v in names: args.append(names[v]) - elif isinstance(v, ConstAddr): - try: - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - except AttributeError: - args.append('ConstAddr(...)') - else: - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) +## elif isinstance(v, ConstAddr): +## try: +## name = ''.join([v.value.ptr.name[i] +## for i in range(len(v.value.ptr.name)-1)]) +## except AttributeError: +## args.append('ConstAddr(...)') +## else: +## args.append( +## 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' +## % name) elif isinstance(v, ConstFloat): args.append('ConstFloat(%r)' % v.value) elif isinstance(v, ConstInt): @@ -264,8 +274,8 @@ fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) - if builder.cpu._overflow_flag: # overflow detected - del builder.cpu._overflow_flag + if builder.fakemetainterp._got_exc: # overflow detected + assert isinstance(builder.fakemetainterp._got_exc, OverflowError) op = ResOperation(rop.GUARD_OVERFLOW, [], None) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including @@ -413,7 +423,7 @@ OPERATIONS.append(UnaryOperation(_op)) OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) -OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True)) +OPERATIONS.append(UnaryOperation(rop.INT_IS_ZERO, boolres=True)) OPERATIONS.append(ConstUnaryOperation(rop.SAME_AS, boolres='sometimes')) for _op in [rop.INT_ADD_OVF, @@ -434,8 +444,6 @@ ]: OPERATIONS.append(UnaryFloatOperation(_op)) -OPERATIONS.append(UnaryFloatOperation(rop.FLOAT_IS_TRUE, boolres=True)) - OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT)) OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT)) @@ -587,8 +595,8 @@ def run_loop(self): cpu = self.builder.cpu self.clear_state() - assert not cpu.get_exception() - assert not cpu.get_exc_value() + exc = cpu.grab_exc_value() + assert not exc for i, box in enumerate(self.startvars): if isinstance(box, BoxInt): @@ -609,15 +617,13 @@ self.expected[v], i) ) + exc = cpu.grab_exc_value() if (self.guard_op is not None and self.guard_op.is_guard_exception()): if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: - assert cpu.get_exception() - assert cpu.get_exc_value() - cpu.clear_exception() + assert exc else: - assert not cpu.get_exception() - assert not cpu.get_exc_value() + assert not exc def build_bridge(self): def exc_handling(guard_op): Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Tue Jun 8 23:42:50 2010 @@ -633,8 +633,8 @@ genop_int_ne = _cmpop("NE", "NE") genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") - genop_oois = genop_int_eq - genop_ooisnot = genop_int_ne + genop_ptr_eq = genop_int_eq + genop_ptr_ne = genop_int_ne genop_float_lt = _cmpop_float('B') genop_float_le = _cmpop_float('BE') @@ -654,8 +654,8 @@ genop_guard_int_ne = _cmpop_guard("NE", "NE", "E", "E") genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") - genop_guard_oois = genop_guard_int_eq - genop_guard_ooisnot = genop_guard_int_ne + genop_guard_ptr_eq = genop_guard_int_eq + genop_guard_ptr_ne = genop_guard_int_ne genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") @@ -689,32 +689,6 @@ # Following what gcc does: res = x & 0x7FFFFFFFFFFFFFFF self.mc.ANDPD(arglocs[0], self.loc_float_const_abs) - def genop_guard_float_is_true(self, op, guard_op, addr, arglocs, resloc): - guard_opnum = guard_op.opnum - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - mc = self.mc._mc - if guard_opnum == rop.GUARD_TRUE: - mc.JP(rel8(6)) - mc.JZ(rel32(addr)) - return mc.tell() - 4 - else: - mc.JP(rel8(2)) - mc.JZ(rel8(5)) - return self.implement_guard(addr, mc.JMP) - - def genop_float_is_true(self, op, arglocs, resloc): - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - rl = resloc.lowest8bits() - rh = resloc.higher8bits() - self.mc.SETNE(rl) - self.mc.SETP(rh) - self.mc.OR(rl, rh) - self.mc.MOVZX(resloc, rl) - def genop_cast_float_to_int(self, op, arglocs, resloc): self.mc.CVTTSD2SI(resloc, arglocs[0]) @@ -753,7 +727,7 @@ self.mc.SETNE(rl) self.mc.MOVZX(resloc, rl) - def genop_guard_bool_not(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_zero(self, op, guard_op, addr, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm8(0)) if guard_opnum == rop.GUARD_TRUE: @@ -761,13 +735,15 @@ else: return self.implement_guard(addr, self.mc.JZ) - def genop_bool_not(self, op, arglocs, resloc): - self.mc.XOR(arglocs[0], imm8(1)) + def genop_int_is_zero(self, op, arglocs, resloc): + self.mc.CMP(arglocs[0], imm8(0)) + rl = resloc.lowest8bits() + self.mc.SETE(rl) + self.mc.MOVZX(resloc, rl) def genop_same_as(self, op, arglocs, resloc): self.mov(arglocs[0], resloc) - genop_cast_ptr_to_int = genop_same_as - genop_virtual_ref = genop_same_as + #genop_cast_ptr_to_int = genop_same_as def genop_int_mod(self, op, arglocs, resloc): self.mc.CDQ() @@ -1115,13 +1091,8 @@ n = self.CODE_HOLE mc.writechr(n) mc.writechr(self.CODE_STOP) - # preallocate the fail_boxes - i = len(failargs) - 1 - if i >= 0: - self.fail_boxes_int.get_addr_for_num(i) - self.fail_boxes_ptr.get_addr_for_num(i) - if self.cpu.supports_floats: - self.fail_boxes_float.get_addr_for_num(i) + # assert that the fail_boxes lists are big enough + assert len(failargs) <= self.fail_boxes_int.SIZE def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager @@ -1165,39 +1136,6 @@ arglocs.append(loc) return arglocs[:] - def make_boxes_from_latest_values(self, bytecode): - bytecode = rffi.cast(rffi.UCHARP, bytecode) - boxes = [] - while 1: - # decode the next instruction from the bytecode - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - kind = code & 3 - while code > 0x7F: - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - index = len(boxes) - if kind == self.DESCR_INT: - box = BoxInt(self.fail_boxes_int.getitem(index)) - elif kind == self.DESCR_REF: - box = BoxPtr(self.fail_boxes_ptr.getitem(index)) - # clear after reading (xxx duplicates - # get_latest_value_ref()) - self.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - elif kind == self.DESCR_FLOAT: - box = BoxFloat(self.fail_boxes_float.getitem(index)) - else: - assert kind == self.DESCR_SPECIAL - if code == self.CODE_STOP: - break - elif code == self.CODE_HOLE: - box = None - else: - assert 0, "bad code" - boxes.append(box) - return boxes - @rgc.no_collect def grab_frame_values(self, bytecode, frame_addr, allregisters): # no malloc allowed here!! @@ -1258,6 +1196,7 @@ # if not we_are_translated(): assert bytecode[4] == 0xCC + self.fail_boxes_count = num fail_index = rffi.cast(rffi.LONGP, bytecode)[0] return fail_index Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Tue Jun 8 23:42:50 2010 @@ -3,7 +3,7 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, ConstAddr, BoxPtr, + ResOperation, BoxPtr, LoopToken, INT, REF, FLOAT) from pypy.jit.backend.x86.ri386 import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr @@ -11,6 +11,7 @@ from pypy.rlib import rgc from pypy.jit.backend.llsupport import symbolic from pypy.jit.backend.x86.jump import remap_frame_layout +from pypy.jit.codewriter import heaptracker from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr @@ -45,8 +46,6 @@ print "convert_to_imm: ConstPtr needs special care" raise AssertionError return imm(rffi.cast(lltype.Signed, c.value)) - elif isinstance(c, ConstAddr): - return imm(ll2ctypes.cast_adr_to_int(c.value)) else: print "convert_to_imm: got a %s" % c raise AssertionError @@ -550,8 +549,8 @@ consider_uint_lt = _consider_compop consider_uint_le = _consider_compop consider_uint_ge = _consider_compop - consider_oois = _consider_compop - consider_ooisnot = _consider_compop + consider_ptr_eq = _consider_compop + consider_ptr_ne = _consider_compop def _consider_float_op(self, op): loc1 = self.xrm.loc(op.args[1]) @@ -593,20 +592,6 @@ self.Perform(op, [loc0], loc0) self.xrm.possibly_free_var(op.args[0]) - def consider_float_is_true(self, op, guard_op): - # doesn't need arg to be in a register - tmpbox0 = TempBox() - loc0 = self.xrm.force_allocate_reg(tmpbox0) - loc1 = self.xrm.loc(op.args[0]) - arglocs = [loc0, loc1] - self.xrm.possibly_free_var(op.args[0]) - self.xrm.possibly_free_var(tmpbox0) - if guard_op is not None: - self.perform_with_guard(op, guard_op, arglocs, None) - else: - loc2 = self.rm.force_allocate_reg(op.result, need_lower_byte=True) - self.Perform(op, arglocs, loc2) - def consider_cast_float_to_int(self, op): loc0 = self.xrm.make_sure_var_in_reg(op.args[0], imm_fine=False) loc1 = self.rm.force_allocate_reg(op.result) @@ -725,7 +710,7 @@ def consider_new_with_vtable(self, op): classint = op.args[0].getint() - descrsize = self.assembler.cpu.class_sizes[classint] + descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint) if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize): self._fastpath_malloc(op, descrsize) self.assembler.set_vtable(eax, imm(classint)) @@ -889,22 +874,14 @@ resloc = self.rm.force_allocate_reg(op.result, need_lower_byte=True) self.Perform(op, [argloc], resloc) - def consider_bool_not(self, op, guard_op): - if guard_op is not None: - # doesn't need arg to be in a register - argloc = self.loc(op.args[0]) - self.rm.possibly_free_var(op.args[0]) - self.perform_with_guard(op, guard_op, [argloc], None) - else: - self.consider_int_neg(op) + consider_int_is_zero = consider_int_is_true def consider_same_as(self, op): argloc = self.loc(op.args[0]) self.possibly_free_var(op.args[0]) resloc = self.force_allocate_reg(op.result) self.Perform(op, [argloc], resloc) - consider_cast_ptr_to_int = consider_same_as - consider_virtual_ref = consider_same_as + #consider_cast_ptr_to_int = consider_same_as def consider_strlen(self, op): base_loc = self.rm.make_sure_var_in_reg(op.args[0], op.args) @@ -963,9 +940,6 @@ def consider_debug_merge_point(self, op): pass - def consider_virtual_ref_finish(self, op): - self.possibly_free_vars(op.args) - def get_mark_gc_roots(self, gcrootmap): shape = gcrootmap.get_basic_shape() for v, val in self.fm.frame_bindings.items(): @@ -973,6 +947,8 @@ assert isinstance(val, MODRM) gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position)) for v, reg in self.rm.reg_bindings.items(): + if reg is eax: + continue # ok to ignore this one if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)): if reg is ebx: gcrootmap.add_ebx(shape) @@ -981,7 +957,8 @@ elif reg is edi: gcrootmap.add_edi(shape) else: - assert reg is eax # ok to ignore this one + print "[get_mark_gc_roots] bogus register", reg + assert False return gcrootmap.compress_callshape(shape) def consider_force_token(self, op): Modified: pypy/trunk/pypy/jit/backend/x86/ri386.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/ri386.py (original) +++ pypy/trunk/pypy/jit/backend/x86/ri386.py Tue Jun 8 23:42:50 2010 @@ -210,7 +210,7 @@ class REL32(OPERAND): width = 4 def __init__(self, absolute_target): - self.absolute_target = absolute_target + self.absolute_target = get_real_int(absolute_target) def assembler(self): return '%d' % (self.absolute_target,) @@ -286,11 +286,14 @@ rel32 = REL32 rel8 = REL8 +def get_real_int(x): + from pypy.rpython.lltypesystem import rffi, lltype + return rffi.cast(lltype.Signed, x) # force as a real int + def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() - if not we_are_translated(): - assert type(value) is int + value = get_real_int(value) if single_byte(value): return imm8(value) else: Modified: pypy/trunk/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/runner.py (original) +++ pypy/trunk/pypy/jit/backend/x86/runner.py Tue Jun 8 23:42:50 2010 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp import history, compile @@ -67,19 +68,20 @@ return self.assembler.fail_boxes_float.getitem(index) def get_latest_value_ref(self, index): - ptrvalue = self.assembler.fail_boxes_ptr.getitem(index) - # clear after reading - self.assembler.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - return ptrvalue + return self.assembler.fail_boxes_ptr.getitem(index) + + def get_latest_value_count(self): + return self.assembler.fail_boxes_count + + def clear_latest_values(self, count): + setitem = self.assembler.fail_boxes_ptr.setitem + null = lltype.nullptr(llmemory.GCREF.TO) + for index in range(count): + setitem(index, null) def get_latest_force_token(self): return self.assembler.fail_ebp + FORCE_INDEX_OFS - def make_boxes_from_latest_values(self, faildescr): - return self.assembler.make_boxes_from_latest_values( - faildescr._x86_failure_recovery_bytecode) - def execute_token(self, executable_token): addr = executable_token._x86_bootstrap_code func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr) @@ -136,9 +138,6 @@ CPU = CPU386 -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(CPU) - # silence warnings history.LoopToken._x86_param_depth = 0 Modified: pypy/trunk/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/support.py (original) +++ pypy/trunk/pypy/jit/backend/x86/support.py Tue Jun 8 23:42:50 2010 @@ -4,6 +4,8 @@ ATP = lltype.GcArray(TP) class ValuesArray(object): + SIZE = size + def __init__(self): self.ar = lltype.malloc(ATP, size, zero=True, immortal=True) Modified: pypy/trunk/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_assembler.py Tue Jun 8 23:42:50 2010 @@ -75,35 +75,6 @@ assert ([loc.assembler() for loc in newlocs] == [loc.assembler() for loc in locs if loc is not None]) - # finally, test make_boxes_from_latest_values(), which should - # reproduce the holes - expected_classes = [BoxInt, BoxPtr, BoxFloat, - BoxInt, BoxPtr, BoxFloat, - type(None), type(None), - BoxInt, BoxPtr, BoxFloat] - ptrvalues = {} - S = lltype.GcStruct('S') - for i, cls in enumerate(expected_classes): - if cls == BoxInt: - assembler.fail_boxes_int.setitem(i, 1000 + i) - elif cls == BoxPtr: - s = lltype.malloc(S) - s_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s) - ptrvalues[i] = s_ref - assembler.fail_boxes_ptr.setitem(i, s_ref) - elif cls == BoxFloat: - assembler.fail_boxes_float.setitem(i, 42.5 + i) - boxes = assembler.make_boxes_from_latest_values(bytecode_addr) - assert len(boxes) == len(locs) == len(expected_classes) - for i, (box, expected_class) in enumerate(zip(boxes, expected_classes)): - assert type(box) is expected_class - if expected_class == BoxInt: - assert box.value == 1000 + i - elif expected_class == BoxPtr: - assert box.value == ptrvalues[i] - elif expected_class == BoxFloat: - assert box.value == 42.5 + i - # ____________________________________________________________ def test_failure_recovery_func_no_floats(): @@ -244,6 +215,13 @@ # bits of the float were correctly saved and restored. assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + # verify that until clear_latest_values() is called, reading the + # same values multiple times work + for i in range(len(content)): + assert assembler.fail_boxes_int.getitem(i) == expected_ints[i] + assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i] + assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + class FakeProfileAgent(object): def __init__(self): self.functions = [] Modified: pypy/trunk/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_basic.py Tue Jun 8 23:42:50 2010 @@ -2,7 +2,7 @@ from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.test import test_basic -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE class Jit386Mixin(test_basic.LLJitMixin): Modified: pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py Tue Jun 8 23:42:50 2010 @@ -6,6 +6,7 @@ from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription from pypy.jit.backend.x86.runner import CPU @@ -225,10 +226,12 @@ self.nodedescr = nodedescr vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) vtable_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable)) - NODE2 = lltype.Struct('node2', ('tid', lltype.Signed), + NODE2 = lltype.GcStruct('node2', + ('parent', rclass.OBJECT), + ('tid', lltype.Signed), ('vtable', lltype.Ptr(rclass.OBJECT_VTABLE))) descrsize = cpu.sizeof(NODE2) - cpu.set_class_sizes({vtable_int: descrsize}) + heaptracker.register_known_gctype(cpu, vtable, NODE2) self.descrsize = descrsize self.vtable_int = vtable_int @@ -282,4 +285,4 @@ assert gc_ll_descr.nursery[0] == self.descrsize.tid assert gc_ll_descr.nursery[1] == self.vtable_int nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + 8 + assert gc_ll_descr.addrs[0] == nurs_adr + 12 Modified: pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py Tue Jun 8 23:42:50 2010 @@ -211,10 +211,9 @@ ''' S = lltype.GcStruct('S') ptr = lltype.malloc(S) + self.cpu.clear_latest_values(2) self.interpret(ops, [0, ptr]) assert self.getptr(0, lltype.Ptr(S)) == ptr - assert not self.cpu.assembler.fail_boxes_ptr.getitem(0) - assert not self.cpu.assembler.fail_boxes_ptr.getitem(1) def test_exception_bridge_no_exception(self): ops = ''' @@ -522,18 +521,20 @@ assert self.getint(0) == 0 def test_bug_float_is_true_stack(self): + # NB. float_is_true no longer exists. Unsure if keeping this test + # makes sense any more. ops = ''' [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9] - i0 = float_is_true(f0) - i1 = float_is_true(f1) - i2 = float_is_true(f2) - i3 = float_is_true(f3) - i4 = float_is_true(f4) - i5 = float_is_true(f5) - i6 = float_is_true(f6) - i7 = float_is_true(f7) - i8 = float_is_true(f8) - i9 = float_is_true(f9) + i0 = float_ne(f0, 0.0) + i1 = float_ne(f1, 0.0) + i2 = float_ne(f2, 0.0) + i3 = float_ne(f3, 0.0) + i4 = float_ne(f4, 0.0) + i5 = float_ne(f5, 0.0) + i6 = float_ne(f6, 0.0) + i7 = float_ne(f7, 0.0) + i8 = float_ne(f8, 0.0) + i9 = float_ne(f9, 0.0) finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) ''' loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9]) Modified: pypy/trunk/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_regalloc2.py Tue Jun 8 23:42:50 2010 @@ -35,7 +35,7 @@ ResOperation(rop.INT_MUL, [v1, v1], v2), ResOperation(rop.INT_MUL, [v2, v1], v3), ResOperation(rop.INT_IS_TRUE, [v2], tmp5), - ResOperation(rop.BOOL_NOT, [tmp5], v4), + ResOperation(rop.INT_IS_ZERO, [tmp5], v4), ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()), ] cpu = CPU(None, None) Modified: pypy/trunk/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_runner.py Tue Jun 8 23:42:50 2010 @@ -259,9 +259,11 @@ self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) if guard == rop.GUARD_FALSE: - assert result == execute(self.cpu, op, None, b).value + assert result == execute(self.cpu, None, + op, None, b).value else: - assert result != execute(self.cpu, op, None, b).value + assert result != execute(self.cpu, None, + op, None, b).value def test_stuff_followed_by_guard(self): @@ -304,7 +306,7 @@ self.cpu.set_future_value_int(i, box.value) self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) - expected = execute(self.cpu, op, None, a, b).value + expected = execute(self.cpu, None, op, None, a, b).value if guard == rop.GUARD_FALSE: assert result == expected else: Modified: pypy/trunk/pypy/jit/backend/x86/test/test_send.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_send.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_send.py Tue Jun 8 23:42:50 2010 @@ -2,7 +2,6 @@ import py from pypy.jit.metainterp.test.test_send import SendTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rlib import jit class TestSend(Jit386Mixin, SendTests): Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py Tue Jun 8 23:42:50 2010 @@ -94,7 +94,7 @@ def run(cbuilder, args=''): # pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': str(pypylog)}) + data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) return data.strip() def compile_and_run(f, gc, **kwds): @@ -174,7 +174,7 @@ def run(self, name, n=2000): pypylog = udir.join('TestCompileHybrid.log') res = self.cbuilder.cmdexec("%s %d" %(name, n), - env={'PYPYLOG': str(pypylog)}) + env={'PYPYLOG': ':%s' % pypylog}) assert int(res) == 20 def run_orig(self, name, n, x): Modified: pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py Tue Jun 8 23:42:50 2010 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.jitprof import Profiler from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.backend.test.support import CCompiledMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.translator.translator import TranslationContext class TestTranslationX86(CCompiledMixin): @@ -38,7 +38,7 @@ return abs(x) jitdriver = JitDriver(greens = [], - reds = ['frame', 'total', 'j'], + reds = ['total', 'frame', 'j'], virtualizables = ['frame']) def f(i, j): for param in unroll_parameters: @@ -72,7 +72,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -127,8 +127,14 @@ def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) + class ImDone(Exception): + def __init__(self, resvalue): + self.resvalue = resvalue + @dont_look_inside - def f(x): + def f(x, total): + if x <= 3: + raise ImDone(total * 10) if x > 20: return 2 raise ValueError @@ -149,16 +155,16 @@ return Sub() else: return Base() - def main(i): + def myportal(i): jitdriver.set_param("threshold", 3) jitdriver.set_param("trace_eagerness", 2) total = 0 n = i - while n > 3: + while True: jitdriver.can_enter_jit(n=n, total=total) jitdriver.jit_merge_point(n=n, total=total) try: - total += f(n) + total += f(n, total) except ValueError: total += 1 try: @@ -166,7 +172,11 @@ except ValueError: total -= 1 n -= h(n).meth() # this is to force a GUARD_CLASS - return total * 10 + def main(i): + try: + myportal(i) + except ImDone, e: + return e.resvalue # XXX custom fishing, depends on the exact env var and format logfile = udir.join('test_ztranslation.log') Modified: pypy/trunk/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/compile.py (original) +++ pypy/trunk/pypy/jit/metainterp/compile.py Tue Jun 8 23:42:50 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import debug_start, debug_stop from pypy.conftest import option +from pypy.tool.sourcetools import func_with_new_name from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import TreeLoop, Box, History, LoopToken @@ -14,8 +15,10 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.jit.metainterp.optimizeutil import InvalidLoop -class GiveUp(Exception): - pass +def giveup(): + from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole + from pypy.jit.metainterp.jitprof import ABORT_BRIDGE + raise SwitchToBlackhole(ABORT_BRIDGE) def show_loop(metainterp_sd, loop=None, error=None): # debugging @@ -153,6 +156,7 @@ assert metainterp_sd.result_type == 'ref' cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): @@ -165,6 +169,7 @@ def handle_fail(self, metainterp_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value) @@ -220,6 +225,11 @@ rd_virtuals = None rd_pendingfields = None + CNT_INT = -0x20000000 + CNT_REF = -0x40000000 + CNT_FLOAT = -0x60000000 + CNT_MASK = 0x1FFFFFFF + def __init__(self, metainterp_sd, original_greenkey): ResumeDescr.__init__(self, original_greenkey) self.metainterp_sd = metainterp_sd @@ -236,23 +246,64 @@ except ValueError: return # xxx probably very rare else: - self._counter = ~i # use ~(index_of_guarded_box_in_fail_args) + if box.type == history.INT: + cnt = self.CNT_INT + elif box.type == history.REF: + cnt = self.CNT_REF + elif box.type == history.FLOAT: + cnt = self.CNT_FLOAT + else: + assert 0, box.type + # we build the following value for _counter, which is always + # a negative value + self._counter = cnt | i def handle_fail(self, metainterp_sd): + if self.must_compile(metainterp_sd): + return self._trace_and_compile_from_bridge(metainterp_sd) + else: + from pypy.jit.metainterp.blackhole import resume_in_blackhole + resume_in_blackhole(metainterp_sd, self) + assert 0, "unreachable" + + def _trace_and_compile_from_bridge(self, metainterp_sd): from pypy.jit.metainterp.pyjitpl import MetaInterp metainterp = MetaInterp(metainterp_sd) return metainterp.handle_guard_failure(self) + _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd, inputargs_and_holes): + def must_compile(self, metainterp_sd): trace_eagerness = metainterp_sd.state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness else: - box = inputargs_and_holes[~self._counter] - if self._counters is None: - self._counters = ResumeGuardCounters() - counter = self._counters.see(box) + index = self._counter & self.CNT_MASK + typetag = self._counter & ~ self.CNT_MASK + counters = self._counters + if typetag == self.CNT_INT: + intvalue = metainterp_sd.cpu.get_latest_value_int(index) + if counters is None: + self._counters = counters = ResumeGuardCountersInt() + else: + assert isinstance(counters, ResumeGuardCountersInt) + counter = counters.see_int(intvalue) + elif typetag == self.CNT_REF: + refvalue = metainterp_sd.cpu.get_latest_value_ref(index) + if counters is None: + self._counters = counters = ResumeGuardCountersRef() + else: + assert isinstance(counters, ResumeGuardCountersRef) + counter = counters.see_ref(refvalue) + elif typetag == self.CNT_FLOAT: + floatvalue = metainterp_sd.cpu.get_latest_value_float(index) + if counters is None: + self._counters = counters = ResumeGuardCountersFloat() + else: + assert isinstance(counters, ResumeGuardCountersFloat) + counter = counters.see_float(floatvalue) + else: + assert 0, typetag return counter >= trace_eagerness def reset_counter_from_failure(self): @@ -283,17 +334,17 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): def handle_fail(self, metainterp_sd): - from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + # Failures of a GUARD_NOT_FORCED are never compiled, but + # always just blackholed. First fish for the data saved when + # the virtualrefs and virtualizable have been forced by + # handle_async_forcing() just a moment ago. + from pypy.jit.metainterp.blackhole import resume_in_blackhole token = metainterp_sd.cpu.get_latest_force_token() all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - metainterp._already_allocated_resume_virtuals = all_virtuals - return metainterp.handle_guard_failure(self) - - def must_compile(self, metainterp_sd, inputargs_and_holes): - return False # never compile GUARD_NOT_FORCED failures + resume_in_blackhole(metainterp_sd, self, all_virtuals) + assert 0, "unreachable" @staticmethod def force_now(cpu, token): @@ -305,91 +356,101 @@ faildescr.handle_async_forcing(token) def handle_async_forcing(self, force_token): - from pypy.jit.metainterp.pyjitpl import MetaInterp from pypy.jit.metainterp.resume import force_from_resumedata - # To handle the forcing itself, we create a temporary MetaInterp - # as a convenience to move the various data to its proper place. metainterp_sd = self.metainterp_sd - metainterp = MetaInterp(metainterp_sd) - metainterp.history = None # blackholing - liveboxes = metainterp_sd.cpu.make_boxes_from_latest_values(self) - # - expect_virtualizable = metainterp_sd.virtualizable_info is not None - forced_data = force_from_resumedata(metainterp, liveboxes, self, - expect_virtualizable) - virtualizable_boxes, virtualref_boxes, all_virtuals = forced_data - # - # Handle virtualref_boxes: mark each JIT_VIRTUAL_REF as forced - vrefinfo = metainterp_sd.virtualref_info - for i in range(0, len(virtualref_boxes), 2): - virtualbox = virtualref_boxes[i] - vrefbox = virtualref_boxes[i+1] - vrefinfo.forced_single_vref(vrefbox.getref_base(), - virtualbox.getref_base()) - # Handle virtualizable_boxes: store them on the real virtualizable now - if expect_virtualizable: - metainterp_sd.virtualizable_info.forced_vable(virtualizable_boxes) + all_virtuals = force_from_resumedata(metainterp_sd, self) + # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED self.save_data(force_token, all_virtuals) def save_data(self, key, value): globaldata = self.metainterp_sd.globaldata - assert key not in globaldata.resume_virtuals - globaldata.resume_virtuals[key] = value + if we_are_translated(): + assert key not in globaldata.resume_virtuals + globaldata.resume_virtuals[key] = value + else: + rv = globaldata.resume_virtuals_not_translated + for key1, value1 in rv: + assert key1 != key + rv.append((key, value)) def fetch_data(self, key): globaldata = self.metainterp_sd.globaldata - assert key in globaldata.resume_virtuals - data = globaldata.resume_virtuals[key] - del globaldata.resume_virtuals[key] + if we_are_translated(): + assert key in globaldata.resume_virtuals + data = globaldata.resume_virtuals[key] + del globaldata.resume_virtuals[key] + else: + rv = globaldata.resume_virtuals_not_translated + for i in range(len(rv)): + if rv[i][0] == key: + data = rv[i][1] + del rv[i] + break + else: + assert 0, "not found: %r" % (key,) return data -class ResumeGuardCounters(object): - # Completely custom algorithm for now: keep 5 pairs (box, counter), +class AbstractResumeGuardCounters(object): + # Completely custom algorithm for now: keep 5 pairs (value, counter), # and when we need more, we discard the middle pair (middle in the # current value of the counter). That way, we tend to keep the - # boxes with a high counter, but also we avoid always throwing away - # the most recently added box. **THIS ALGO MUST GO AWAY AT SOME POINT** + # values with a high counter, but also we avoid always throwing away + # the most recently added value. **THIS ALGO MUST GO AWAY AT SOME POINT** + pass +def _see(self, newvalue): + # find and update an existing counter + unused = -1 + for i in range(5): + cnt = self.counters[i] + if cnt: + if self.values[i] == newvalue: + cnt += 1 + self.counters[i] = cnt + return cnt + else: + unused = i + # not found. Use a previously unused entry, if there is one + if unused >= 0: + self.counters[unused] = 1 + self.values[unused] = newvalue + return 1 + # no unused entry. Overwrite the middle one. Computed with indices + # a, b, c meaning the highest, second highest, and third highest + # entries. + a = 0 + b = c = -1 + for i in range(1, 5): + if self.counters[i] > self.counters[a]: + c = b; b = a; a = i + elif b < 0 or self.counters[i] > self.counters[b]: + c = b; b = i + elif c < 0 or self.counters[i] > self.counters[c]: + c = i + self.counters[c] = 1 + self.values[c] = newvalue + return 1 + +class ResumeGuardCountersInt(AbstractResumeGuardCounters): def __init__(self): self.counters = [0] * 5 - self.boxes = [None] * 5 + self.values = [0] * 5 + see_int = func_with_new_name(_see, 'see_int') - def see(self, newbox): - newbox = newbox.constbox() - # find and update an existing counter - unused = -1 - for i in range(5): - cnt = self.counters[i] - if cnt: - if newbox.same_constant(self.boxes[i]): - cnt += 1 - self.counters[i] = cnt - return cnt - else: - unused = i - # not found. Use a previously unused entry, if there is one - if unused >= 0: - self.counters[unused] = 1 - self.boxes[unused] = newbox - return 1 - # no unused entry. Overwrite the middle one. Computed with indices - # a, b, c meaning the highest, second highest, and third highest - # entries. - a = 0 - b = c = -1 - for i in range(1, 5): - if self.counters[i] > self.counters[a]: - c = b; b = a; a = i - elif b < 0 or self.counters[i] > self.counters[b]: - c = b; b = i - elif c < 0 or self.counters[i] > self.counters[c]: - c = i - self.counters[c] = 1 - self.boxes[c] = newbox - return 1 +class ResumeGuardCountersRef(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [history.ConstPtr.value] * 5 + see_ref = func_with_new_name(_see, 'see_ref') + +class ResumeGuardCountersFloat(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [0.0] * 5 + see_float = func_with_new_name(_see, 'see_float') class ResumeFromInterpDescr(ResumeDescr): Modified: pypy/trunk/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/executor.py Tue Jun 8 23:42:50 2010 @@ -2,248 +2,232 @@ """ import py -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, check_descr -from pypy.jit.metainterp.history import INT, REF, ConstFloat +from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, check_descr +from pypy.jit.metainterp.history import INT, REF, FLOAT, VOID, AbstractDescr from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop - - -# Operations in the _ALWAYS_PURE part of the table of resoperation.py -# must return a ConstInt or ConstPtr. Other operations must return -# a BoxInt or BoxPtr or None. +from pypy.jit.metainterp.blackhole import BlackholeInterpreter, NULL # ____________________________________________________________ -def do_int_add(cpu, box1, box2): - return ConstInt(intmask(box1.getint() + box2.getint())) - -def do_int_sub(cpu, box1, box2): - return ConstInt(intmask(box1.getint() - box2.getint())) - -def do_int_mul(cpu, box1, box2): - return ConstInt(intmask(box1.getint() * box2.getint())) - -def do_int_floordiv(cpu, box1, box2): - z = llop.int_floordiv(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_uint_floordiv(cpu, box1, box2): - z = llop.uint_floordiv(lltype.Unsigned, r_uint(box1.getint()), - r_uint(box2.getint())) - return ConstInt(intmask(z)) - -def do_int_mod(cpu, box1, box2): - z = llop.int_mod(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_int_and(cpu, box1, box2): - return ConstInt(box1.getint() & box2.getint()) - -def do_int_or(cpu, box1, box2): - return ConstInt(box1.getint() | box2.getint()) - -def do_int_xor(cpu, box1, box2): - return ConstInt(box1.getint() ^ box2.getint()) - -def do_int_rshift(cpu, box1, box2): - return ConstInt(box1.getint() >> box2.getint()) - -def do_int_lshift(cpu, box1, box2): - return ConstInt(intmask(box1.getint() << box2.getint())) - -def do_uint_rshift(cpu, box1, box2): - v = r_uint(box1.getint()) >> r_uint(box2.getint()) - return ConstInt(intmask(v)) - -# ---------- - -def do_int_lt(cpu, box1, box2): - return ConstInt(box1.getint() < box2.getint()) - -def do_int_le(cpu, box1, box2): - return ConstInt(box1.getint() <= box2.getint()) - -def do_int_eq(cpu, box1, box2): - return ConstInt(box1.getint() == box2.getint()) - -def do_int_ne(cpu, box1, box2): - return ConstInt(box1.getint() != box2.getint()) - -def do_int_gt(cpu, box1, box2): - return ConstInt(box1.getint() > box2.getint()) - -def do_int_ge(cpu, box1, box2): - return ConstInt(box1.getint() >= box2.getint()) - -def do_uint_lt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) < r_uint(box2.getint())) - -def do_uint_le(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) <= r_uint(box2.getint())) - -def do_uint_gt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) > r_uint(box2.getint())) - -def do_uint_ge(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) >= r_uint(box2.getint())) - -# ---------- - -def do_int_is_true(cpu, box1): - return ConstInt(bool(box1.getint())) - -def do_int_neg(cpu, box1): - return ConstInt(intmask(-box1.getint())) - -def do_int_invert(cpu, box1): - return ConstInt(~box1.getint()) - -def do_bool_not(cpu, box1): - return ConstInt(not box1.getint()) +def _prepare_call(argboxes, descr): + # count the number of arguments of the different types + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + type = argboxes[i].type + if type == INT: count_i += 1 + elif type == REF: count_r += 1 + elif type == FLOAT: count_f += 1 + # allocate lists for each type that has at least one argument + if count_i: args_i = [0] * count_i + else: args_i = None + if count_r: args_r = [NULL] * count_r + else: args_r = None + if count_f: args_f = [0.0] * count_f + else: args_f = None + # fill in the lists + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + box = argboxes[i] + if box.type == INT: + args_i[count_i] = box.getint() + count_i += 1 + elif box.type == REF: + args_r[count_r] = box.getref_base() + count_r += 1 + elif box.type == FLOAT: + args_f[count_f] = box.getfloat() + count_f += 1 + # get the function address as an integer + func = argboxes[0].getint() + # do the call using the correct function from the cpu + rettype = descr.get_return_type() + return func, args_i, args_r, args_f, rettype + +def do_call(cpu, metainterp, argboxes, descr): + assert metainterp is not None + func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) + if rettype == INT: + try: + result = cpu.bh_call_i(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0 + return BoxInt(result) + if rettype == REF: + try: + result = cpu.bh_call_r(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = NULL + return BoxPtr(result) + if rettype == FLOAT: + try: + result = cpu.bh_call_f(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0.0 + return BoxFloat(result) + if rettype == VOID: + try: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + return None + raise AssertionError("bad rettype") + +do_call_loopinvariant = do_call +do_call_may_force = do_call + +def do_call_pure(cpu, _, argboxes, descr): + # this version does not deal with exceptions at all + # xxx in case of MemoryError, it crashes the JIT + func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) + if rettype == INT: + return BoxInt(cpu.bh_call_i(func, descr, args_i, args_r, args_f)) + if rettype == REF: + return BoxPtr(cpu.bh_call_r(func, descr, args_i, args_r, args_f)) + if rettype == FLOAT: + return BoxFloat(cpu.bh_call_f(func, descr, args_i, args_r, args_f)) + if rettype == VOID: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + return None + raise AssertionError("bad rettype") + +def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + return BoxPtr(cpu.bh_getarrayitem_gc_r(arraydescr, array, index)) + elif arraydescr.is_array_of_floats(): + return BoxFloat(cpu.bh_getarrayitem_gc_f(arraydescr, array, index)) + else: + return BoxInt(cpu.bh_getarrayitem_gc_i(arraydescr, array, index)) -def do_same_as(cpu, box1): - return box1 +def do_setarrayitem_gc(cpu, _, arraybox, indexbox, itembox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + cpu.bh_setarrayitem_gc_r(arraydescr, array, index, + itembox.getref_base()) + elif arraydescr.is_array_of_floats(): + cpu.bh_setarrayitem_gc_f(arraydescr, array, index, itembox.getfloat()) + else: + cpu.bh_setarrayitem_gc_i(arraydescr, array, index, itembox.getint()) -def do_oois(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() == box2.getint() - elif tp == REF: - x = box1.getref_base() == box2.getref_base() +def do_getfield_gc(cpu, _, structbox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr)) -def do_ooisnot(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() != box2.getint() - elif tp == REF: - x = box1.getref_base() != box2.getref_base() +def do_getfield_raw(cpu, _, structbox, fielddescr): + check_descr(fielddescr) + struct = structbox.getint() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr)) -def do_subclassof(cpu, box1, box2): - return ConstInt(cpu.ts.subclassOf(cpu, box1, box2)) +def do_setfield_gc(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_gc_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_gc_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_gc_i(struct, fielddescr, itembox.getint()) -# ---------- +def do_setfield_raw(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getint() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_raw_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_raw_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_raw_i(struct, fielddescr, itembox.getint()) -def do_int_add_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def exec_new_with_vtable(cpu, clsbox): + from pypy.jit.codewriter import heaptracker + vtable = clsbox.getint() + descr = heaptracker.vtable2descr(cpu, vtable) + return cpu.bh_new_with_vtable(descr, vtable) + +def do_new_with_vtable(cpu, _, clsbox): + return BoxPtr(exec_new_with_vtable(cpu, clsbox)) + +def do_arraycopy(cpu, _, calldescr, funcbox, x1box, x2box, + x3box, x4box, x5box, arraydescr): + cpu.bh_call_v(funcbox.getint(), calldescr, + [x3box.getint(), x4box.getint(), x5box.getint()], + [x1box.getref_base(), x2box.getref_base()], None) + +def do_int_add_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x + y) + z = ovfcheck(a + b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_sub_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_sub_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x - y) + z = ovfcheck(a - b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_mul_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_mul_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x * y) + z = ovfcheck(a * b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -# ---------- - -def do_float_neg(cpu, box1): - return ConstFloat(-box1.getfloat()) - -def do_float_abs(cpu, box1): - return ConstFloat(abs(box1.getfloat())) - -def do_float_is_true(cpu, box1): - return ConstInt(bool(box1.getfloat())) - -def do_float_add(cpu, box1, box2): - return ConstFloat(box1.getfloat() + box2.getfloat()) - -def do_float_sub(cpu, box1, box2): - return ConstFloat(box1.getfloat() - box2.getfloat()) - -def do_float_mul(cpu, box1, box2): - return ConstFloat(box1.getfloat() * box2.getfloat()) - -def do_float_truediv(cpu, box1, box2): - return ConstFloat(box1.getfloat() / box2.getfloat()) - -def do_float_lt(cpu, box1, box2): - return ConstInt(box1.getfloat() < box2.getfloat()) - -def do_float_le(cpu, box1, box2): - return ConstInt(box1.getfloat() <= box2.getfloat()) - -def do_float_eq(cpu, box1, box2): - return ConstInt(box1.getfloat() == box2.getfloat()) - -def do_float_ne(cpu, box1, box2): - return ConstInt(box1.getfloat() != box2.getfloat()) - -def do_float_gt(cpu, box1, box2): - return ConstInt(box1.getfloat() > box2.getfloat()) - -def do_float_ge(cpu, box1, box2): - return ConstInt(box1.getfloat() >= box2.getfloat()) - -def do_cast_float_to_int(cpu, box1): - # note: we need to call int() twice to care for the fact that - # int(-2147483648.0) returns a long :-( - return ConstInt(int(int(box1.getfloat()))) - -def do_cast_int_to_float(cpu, box1): - return ConstFloat(float(box1.getint())) +def do_same_as(cpu, _, box): + return box.clonebox() # ____________________________________________________________ -def do_force_token(cpu): - raise NotImplementedError +##def do_force_token(cpu): +## raise NotImplementedError -def do_virtual_ref(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref(cpu, box1, box2): +## raise NotImplementedError -def do_virtual_ref_finish(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref_finish(cpu, box1, box2): +## raise NotImplementedError -def do_debug_merge_point(cpu, box1): - from pypy.jit.metainterp.warmspot import get_stats - loc = box1._get_str() - get_stats().add_merge_point_location(loc) +##def do_debug_merge_point(cpu, box1): +## from pypy.jit.metainterp.warmspot import get_stats +## loc = box1._get_str() +## get_stats().add_merge_point_location(loc) # ____________________________________________________________ -def make_execute_list(cpuclass): - from pypy.jit.backend.model import AbstractCPU +def _make_execute_list(): if 0: # enable this to trace calls to do_xxx def wrap(fn): def myfn(*args): @@ -266,37 +250,109 @@ # find which list to store the operation in, based on num_args num_args = resoperation.oparity[value] withdescr = resoperation.opwithdescr[value] - if withdescr and num_args >= 0: - num_args += 1 - if num_args not in execute_by_num_args: - execute_by_num_args[num_args] = [None] * (rop._LAST+1) - execute = execute_by_num_args[num_args] + dictkey = num_args, withdescr + if dictkey not in execute_by_num_args: + execute_by_num_args[dictkey] = [None] * (rop._LAST+1) + execute = execute_by_num_args[dictkey] # if execute[value] is not None: - raise Exception("duplicate entry for op number %d" % value) + raise AssertionError("duplicate entry for op number %d"% value) + # + # Fish for a way for the pyjitpl interpreter to delegate + # really running the operation to the blackhole interpreter + # or directly to the cpu. First try the do_xxx() functions + # explicitly encoded above: + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # Maybe the same without the _PURE suffix? if key.endswith('_PURE'): key = key[:-5] - name = 'do_' + key.lower() - if hasattr(cpuclass, name): - execute[value] = wrap(getattr(cpuclass, name)) - elif name in globals(): - execute[value] = wrap(globals()[name]) - else: - assert hasattr(AbstractCPU, name), name - cpuclass._execute_by_num_args = execute_by_num_args + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # If missing, fallback to the bhimpl_xxx() method of the + # blackhole interpreter. This only works if there is a + # method of the exact same name and it accepts simple + # parameters. + name = 'bhimpl_' + key.lower() + if hasattr(BlackholeInterpreter, name): + func = make_execute_function_with_boxes( + key.lower(), + getattr(BlackholeInterpreter, name).im_func) + if func is not None: + execute[value] = func + continue + if value in (rop.FORCE_TOKEN, + rop.CALL_ASSEMBLER, + rop.COND_CALL_GC_WB, + rop.DEBUG_MERGE_POINT, + rop.SETARRAYITEM_RAW, + ): # list of opcodes never executed by pyjitpl + continue + raise AssertionError("missing %r" % (key,)) + return execute_by_num_args +def make_execute_function_with_boxes(name, func): + # Make a wrapper for 'func'. The func is a simple bhimpl_xxx function + # from the BlackholeInterpreter class. The wrapper is a new function + # that receives and returns boxed values. + for argtype in func.argtypes: + if argtype not in ('i', 'r', 'f', 'd', 'cpu'): + return None + if list(func.argtypes).count('d') > 1: + return None + if func.resulttype not in ('i', 'r', 'f', None): + return None + argtypes = unrolling_iterable(func.argtypes) + resulttype = func.resulttype + # + def do(cpu, _, *argboxes): + newargs = () + for argtype in argtypes: + if argtype == 'cpu': + value = cpu + elif argtype == 'd': + value = argboxes[-1] + assert isinstance(value, AbstractDescr) + argboxes = argboxes[:-1] + else: + argbox = argboxes[0] + argboxes = argboxes[1:] + if argtype == 'i': value = argbox.getint() + elif argtype == 'r': value = argbox.getref_base() + elif argtype == 'f': value = argbox.getfloat() + newargs = newargs + (value,) + assert not argboxes + # + result = func(*newargs) + # + if resulttype == 'i': return BoxInt(result) + if resulttype == 'r': return BoxPtr(result) + if resulttype == 'f': return BoxFloat(result) + return None + # + do.func_name = 'do_' + name + return do -def get_execute_funclist(cpu, num_args): +def get_execute_funclist(num_args, withdescr): # workaround, similar to the next one - return cpu._execute_by_num_args[num_args] + return EXECUTE_BY_NUM_ARGS[num_args, withdescr] get_execute_funclist._annspecialcase_ = 'specialize:memo' -def get_execute_function(cpu, opnum, num_args): +def get_execute_function(opnum, num_args, withdescr): # workaround for an annotation limitation: putting this code in # a specialize:memo function makes sure the following line is # constant-folded away. Only works if opnum and num_args are # constants, of course. - return cpu._execute_by_num_args[num_args][opnum] + func = EXECUTE_BY_NUM_ARGS[num_args, withdescr][opnum] + assert func is not None, "EXECUTE_BY_NUM_ARGS[%s, %s][%s]" % ( + num_args, withdescr, resoperation.opname[opnum]) + return func get_execute_function._annspecialcase_ = 'specialize:memo' def has_descr(opnum): @@ -305,56 +361,61 @@ has_descr._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, descr, *argboxes): +def execute(cpu, metainterp, opnum, descr, *argboxes): # only for opnums with a fixed arity - if has_descr(opnum): + num_args = len(argboxes) + withdescr = has_descr(opnum) + if withdescr: check_descr(descr) argboxes = argboxes + (descr,) else: assert descr is None - func = get_execute_function(cpu, opnum, len(argboxes)) - assert func is not None - return func(cpu, *argboxes) -execute._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, num_args, withdescr) + return func(cpu, metainterp, *argboxes) # note that the 'argboxes' tuple + # optionally ends with the descr +execute._annspecialcase_ = 'specialize:arg(2)' -def execute_varargs(cpu, opnum, argboxes, descr): +def execute_varargs(cpu, metainterp, opnum, argboxes, descr): # only for opnums with a variable arity (calls, typically) check_descr(descr) - func = get_execute_function(cpu, opnum, -1) - assert func is not None - return func(cpu, argboxes, descr) -execute_varargs._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, -1, True) + return func(cpu, metainterp, argboxes, descr) +execute_varargs._annspecialcase_ = 'specialize:arg(2)' -def execute_nonspec(cpu, opnum, argboxes, descr=None): +def execute_nonspec(cpu, metainterp, opnum, argboxes, descr=None): arity = resoperation.oparity[opnum] assert arity == -1 or len(argboxes) == arity if resoperation.opwithdescr[opnum]: check_descr(descr) if arity == -1: - func = get_execute_funclist(cpu, -1)[opnum] - return func(cpu, argboxes, descr) + func = get_execute_funclist(-1, True)[opnum] + return func(cpu, metainterp, argboxes, descr) if arity == 0: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, descr) + func = get_execute_funclist(0, True)[opnum] + return func(cpu, metainterp, descr) if arity == 1: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], descr) + func = get_execute_funclist(1, True)[opnum] + return func(cpu, metainterp, argboxes[0], descr) if arity == 2: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], descr) + func = get_execute_funclist(2, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], descr) if arity == 3: - func = get_execute_funclist(cpu, 4)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2], descr) + func = get_execute_funclist(3, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2], + descr) else: assert descr is None if arity == 1: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, argboxes[0]) + func = get_execute_funclist(1, False)[opnum] + return func(cpu, metainterp, argboxes[0]) if arity == 2: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], argboxes[1]) + func = get_execute_funclist(2, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1]) if arity == 3: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2]) + func = get_execute_funclist(3, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2]) raise NotImplementedError + + +EXECUTE_BY_NUM_ARGS = _make_execute_list() Modified: pypy/trunk/pypy/jit/metainterp/history.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/history.py (original) +++ pypy/trunk/pypy/jit/metainterp/history.py Tue Jun 8 23:42:50 2010 @@ -9,6 +9,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -16,6 +17,7 @@ REF = 'r' FLOAT = 'f' HOLE = '_' +VOID = 'v' FAILARGS_LIMIT = 1000 @@ -40,6 +42,7 @@ return "ref" else: raise NotImplementedError("type %s not supported" % TYPE) +getkind._annspecialcase_ = 'specialize:memo' def repr_pointer(box): from pypy.rpython.lltypesystem import rstr @@ -98,7 +101,7 @@ def nonconstbox(self): raise NotImplementedError - def getaddr(self, cpu): + def getaddr(self): raise NotImplementedError def sort_key(self): @@ -125,6 +128,18 @@ def _clone_if_mutable(self): return self + def get_arg_types(self): + """ Implement in call descr. + Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). + """ + raise NotImplementedError + + def get_return_type(self): + """ Implement in call descr. + Must return INT, REF, FLOAT, or 'v' for void. + """ + raise NotImplementedError + def get_extra_info(self): """ Implement in call descr """ @@ -150,6 +165,12 @@ """ raise NotImplementedError + def as_vtable_size_descr(self): + """ Implement for size descr representing objects with vtables. + Returns self. (it's an annotation hack) + """ + raise NotImplementedError + class AbstractFailDescr(AbstractDescr): index = -1 @@ -176,18 +197,13 @@ __slots__ = () @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): - if not we_are_translated(): - # cannot store integers representing casted addresses - # inside ConstInt() instances that are going through - # translation; must use the special ConstAddr instead. - return ConstAddr(x, cpu) - intval = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) @@ -216,15 +232,13 @@ # to get the other behavior (i.e. using this __eq__). if self.__class__ is not other.__class__: return False - if isinstance(self.value, Symbolic): - v1 = "symbolic", id(self.value) - else: - v1 = self.value - if isinstance(other.value, Symbolic): - v2 = "symbolic", id(other.value) - else: - v2 = other.value - return v1 == v2 + try: + return self.value == other.value + except TypeError: + if (isinstance(self.value, Symbolic) and + isinstance(other.value, Symbolic)): + return self.value is other.value + raise def __ne__(self, other): return not (self == other) @@ -232,6 +246,7 @@ class ConstInt(Const): type = INT + value = 0 _attrs_ = ('value',) def __init__(self, value): @@ -250,11 +265,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -275,50 +290,6 @@ CONST_FALSE = ConstInt(0) CONST_TRUE = ConstInt(1) -class ConstAddr(Const): # only for constants built before translation - type = INT - _attrs_ = ('value', 'cpu') - - def __init__(self, adrvalue, cpu): - "NOT_RPYTHON" - assert not we_are_translated() - if isinstance(lltype.typeOf(adrvalue), lltype.Ptr): - adrvalue = llmemory.cast_ptr_to_adr(adrvalue) # convenience - else: - assert lltype.typeOf(adrvalue) == llmemory.Address - self.value = adrvalue - self.cpu = cpu - - def clonebox(self): - return BoxInt(self.cpu.cast_adr_to_int(self.value)) - - nonconstbox = clonebox - - def getint(self): - return self.cpu.cast_adr_to_int(self.value) - - def getaddr(self, cpu): - return self.value - - def _get_hash_(self): - return llmemory.cast_adr_to_int(self.value) - - def set_future_value(self, cpu, j): - cpu.set_future_value_int(j, self.getint()) - - def same_constant(self, other): - assert isinstance(other, Const) - return self.value == other.getaddr(self.cpu) - - def nonnull(self): - return bool(self.value) - - def _getrepr_(self): - return self.value - - def repr_rpython(self): - return repr_rpython(self, 'ca') - class ConstFloat(Const): type = FLOAT value = 0.0 @@ -355,6 +326,8 @@ def repr_rpython(self): return repr_rpython(self, 'cf') +CONST_FZERO = ConstFloat(0.0) + class ConstPtr(Const): type = REF value = lltype.nullptr(llmemory.GCREF.TO) @@ -382,7 +355,7 @@ else: return 0 - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def set_future_value(self, cpu, j): @@ -403,7 +376,13 @@ def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr - return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) + try: + return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), + self.value)) + except lltype.UninitializedMemoryAccess: + return '' + +CONST_NULL = ConstPtr(ConstPtr.value) class ConstObj(Const): type = REF @@ -435,7 +414,7 @@ def set_future_value(self, cpu, j): cpu.set_future_value_ref(j, self.value) -## def getaddr(self, cpu): +## def getaddr(self): ## # so far this is used only when calling ## # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a ## # real addr, but just a key for the dictionary @@ -464,7 +443,7 @@ is_box = True # hint that we want to make links in graphviz from this @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": @@ -527,11 +506,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -598,7 +577,7 @@ return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def _get_hash_(self): @@ -694,6 +673,13 @@ except lltype.DelayedPointer: return -2 # xxx risk of changing hash... +def make_hashable_int(i): + if not we_are_translated() and isinstance(i, llmemory.AddressAsInt): + # Warning: such a hash changes at the time of translation + adr = heaptracker.int2adr(i) + return llmemory.cast_adr_to_int(adr, "emulated") + return i + # ____________________________________________________________ # The TreeLoop class contains a loop or a generalized loop, i.e. a tree @@ -845,16 +831,6 @@ op = ResOperation(opnum, argboxes, resbox, descr) self.operations[position] = op - def slice_history_at(self, position): - """ a strange function that does this: - history : operation_at_position : rest - it'll kill operation_at_position, store everything before that - in history.operations and return rest - """ - rest = self.operations[position + 1:] - del self.operations[position:] - return rest - # ____________________________________________________________ Modified: pypy/trunk/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/jitprof.py (original) +++ pypy/trunk/pypy/jit/metainterp/jitprof.py Tue Jun 8 23:42:50 2010 @@ -5,6 +5,7 @@ import os import time from pypy.rlib.debug import debug_print +from pypy.jit.metainterp.jitexc import JitException counters=""" TRACING @@ -13,7 +14,6 @@ BLACKHOLE OPS RECORDED_OPS -BLACKHOLED_OPS GUARDS OPT_OPS OPT_GUARDS @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 5 # one for TOTAL, 5 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 4 # one for TOTAL, 4 for calls, update if needed class BaseProfiler(object): pass @@ -97,7 +97,7 @@ self.t1 = self.starttime self.times = [0, 0] self.counters = [0] * ncounters - self.calls = [[0, 0], [0, 0], [0, 0]] + self.calls = [[0, 0], [0, 0]] self.current = [] def finish(self): @@ -150,10 +150,10 @@ def count_ops(self, opnum, kind=OPS): from pypy.jit.metainterp.resoperation import rop self.counters[kind] += 1 - if opnum == rop.CALL or opnum == rop.OOSEND: + if opnum == rop.CALL: # or opnum == rop.OOSEND: self.calls[kind-OPS][0] += 1 - elif opnum == rop.CALL_PURE or opnum == rop.OOSEND_PURE: - self.calls[kind-OPS][1] += 1 + elif opnum == rop.CALL_PURE: # or opnum == rop.OOSEND_PURE: + self.calls[kind-OPS][1] += 1 def print_stats(self): cnt = self.counters @@ -172,8 +172,6 @@ self._print_intline(" calls", calls[1][0]) self._print_intline(" pure calls", calls[1][1]) self._print_intline("guards", cnt[GUARDS]) - self._print_intline("blackholed ops", calls[2][0]) - self._print_intline(" pure calls", calls[2][1]) self._print_intline("opt ops", cnt[OPT_OPS]) self._print_intline("opt guards", cnt[OPT_GUARDS]) self._print_intline("forcings", cnt[OPT_FORCINGS]) @@ -195,5 +193,5 @@ -class BrokenProfilerData(Exception): +class BrokenProfilerData(JitException): pass Modified: pypy/trunk/pypy/jit/metainterp/logger.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/logger.py (original) +++ pypy/trunk/pypy/jit/metainterp/logger.py Tue Jun 8 23:42:50 2010 @@ -1,9 +1,11 @@ import os from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, \ - BoxInt, ConstAddr, ConstFloat, BoxFloat, AbstractFailDescr + BoxInt, ConstFloat, BoxFloat, AbstractFailDescr class Logger(object): @@ -46,10 +48,16 @@ mv = len(memo) memo[arg] = mv if isinstance(arg, ConstInt): + if int_could_be_an_address(arg.value): + addr = arg.getaddr() + name = self.metainterp_sd.get_name_from_address(addr) + if name: + return 'ConstClass(' + name + ')' return str(arg.value) elif isinstance(arg, BoxInt): return 'i' + str(mv) elif isinstance(arg, self.ts.ConstRef): + # XXX for ootype, this should also go through get_name_from_address return 'ConstPtr(ptr' + str(mv) + ')' elif isinstance(arg, self.ts.BoxRef): return 'p' + str(mv) @@ -57,12 +65,6 @@ return str(arg.value) elif isinstance(arg, BoxFloat): return 'f' + str(mv) - elif isinstance(arg, self.ts.ConstAddr): - addr = arg.getaddr(self.metainterp_sd.cpu) - name = self.metainterp_sd.get_name_from_address(addr) - if not name: - name = 'cls' + str(mv) - return 'ConstClass(' + name + ')' elif arg is None: return 'None' else: @@ -102,3 +104,11 @@ fail_args = '' debug_print(res + op.getopname() + '(' + args + ')' + fail_args) + + +def int_could_be_an_address(x): + if we_are_translated(): + x = rffi.cast(lltype.Signed, x) # force it + return not (-32768 <= x <= 32767) + else: + return isinstance(x, llmemory.AddressAsInt) Modified: pypy/trunk/pypy/jit/metainterp/optimizefindnode.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizefindnode.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizefindnode.py Tue Jun 8 23:42:50 2010 @@ -160,7 +160,8 @@ else: # all constant arguments: we can constant-fold argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.set_constant_node(op.result, resbox.constbox()) # default case: mark the arguments as escaping for box in op.args: @@ -169,8 +170,8 @@ def find_nodes_no_escape(self, op): pass # for operations that don't escape their arguments - find_nodes_OOIS = find_nodes_no_escape - find_nodes_OOISNOT = find_nodes_no_escape + find_nodes_PTR_EQ = find_nodes_no_escape + find_nodes_PTR_NE = find_nodes_no_escape find_nodes_INSTANCEOF = find_nodes_no_escape find_nodes_GUARD_NONNULL = find_nodes_no_escape find_nodes_GUARD_ISNULL = find_nodes_no_escape Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py Tue Jun 8 23:42:50 2010 @@ -16,7 +16,7 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype -from pypy.jit.metainterp.history import AbstractDescr +from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int def optimize_loop_1(metainterp_sd, loop): """Optimize loop.operations to make it match the input of loop.specnodes @@ -89,7 +89,7 @@ if level == LEVEL_KNOWNCLASS: return self.known_class elif level == LEVEL_CONSTANT: - return cpu.ts.cls_of_box(cpu, self.box) + return cpu.ts.cls_of_box(self.box) else: return None @@ -564,7 +564,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) newboxes = modifier.finish(self.values, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here - raise compile.GiveUp + compile.giveup() descr.store_final_boxes(op, newboxes) # if op.opnum == rop.GUARD_VALUE: @@ -594,7 +594,8 @@ else: # all constant arguments: constant-fold away argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.make_constant(op.result, resbox.constbox()) return @@ -747,6 +748,9 @@ def optimize_INT_IS_TRUE(self, op): self._optimize_nullness(op, op.args[0], True) + def optimize_INT_IS_ZERO(self, op): + self._optimize_nullness(op, op.args[0], False) + def _optimize_oois_ooisnot(self, op, expect_isnot): value0 = self.getvalue(op.args[0]) value1 = self.getvalue(op.args[1]) @@ -775,10 +779,10 @@ return self.optimize_default(op) - def optimize_OOISNOT(self, op): + def optimize_PTR_NE(self, op): self._optimize_oois_ooisnot(op, True) - def optimize_OOIS(self, op): + def optimize_PTR_EQ(self, op): self._optimize_oois_ooisnot(op, False) def optimize_VIRTUAL_REF(self, op): @@ -944,7 +948,8 @@ if not funcvalue.is_constant(): self.optimize_default(op) return - resvalue = self.loop_invariant_results.get(op.args[0].getint(), None) + key = make_hashable_int(op.args[0].getint()) + resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: self.make_equal_to(op.result, resvalue) return @@ -953,7 +958,7 @@ op.opnum = rop.CALL self.optimize_default(op) resvalue = self.getvalue(op.result) - self.loop_invariant_results[op.args[0].getint()] = resvalue + self.loop_invariant_results[key] = resvalue def optimize_INT_AND(self, op): v1 = self.getvalue(op.args[0]) @@ -1101,7 +1106,7 @@ del self.cached_arrayitems[arraydescr] except KeyError: pass - if effectinfo.forces_virtual_or_virtualizable: + if effectinfo.check_forces_virtual_or_virtualizable(): vrefinfo = self.optimizer.metainterp_sd.virtualref_info self.force_lazy_setfield(vrefinfo.descr_forced) # ^^^ we only need to force this field; the other fields Modified: pypy/trunk/pypy/jit/metainterp/optimizeutil.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizeutil.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizeutil.py Tue Jun 8 23:42:50 2010 @@ -2,8 +2,9 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp import resoperation, history +from pypy.jit.metainterp.jitexc import JitException -class InvalidLoop(Exception): +class InvalidLoop(JitException): """Raised when the optimize*.py detect that the loop that we are trying to build cannot possibly make sense as a long-running loop (e.g. it cannot run 2 complete iterations).""" Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Tue Jun 8 23:42:50 2010 @@ -1,205 +1,170 @@ import py, os -from pypy.rpython.lltypesystem import llmemory -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.debug import make_sure_not_resized +from pypy.rlib import nonconst from pypy.jit.metainterp import history, compile, resume -from pypy.jit.metainterp.history import Const, ConstInt, Box +from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat +from pypy.jit.metainterp.history import Box from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp import codewriter, executor +from pypy.jit.metainterp import executor from pypy.jit.metainterp.logger import Logger -from pypy.jit.metainterp.jitprof import BLACKHOLED_OPS, EmptyProfiler +from pypy.jit.metainterp.jitprof import EmptyProfiler from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE +from pypy.jit.metainterp.jitexc import JitException, get_llexception from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED -from pypy.jit.metainterp.compile import GiveUp +from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ -def check_args(*args): - for arg in args: - assert isinstance(arg, (Box, Const)) - -class arguments(object): - def __init__(self, *argtypes): - self.argtypes = argtypes - - def __eq__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes == other.argtypes - - def __ne__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes != other.argtypes - - def __call__(self, func): - argtypes = unrolling_iterable(self.argtypes) - def wrapped(self, orgpc): - args = (self, ) - for argspec in argtypes: - if argspec == "box": - box = self.load_arg() - args += (box, ) - elif argspec == "constbox": - args += (self.load_const_arg(), ) - elif argspec == "int": - args += (self.load_int(), ) - elif argspec == "jumptarget": - args += (self.load_3byte(), ) - elif argspec == "jumptargets": - num = self.load_int() - args += ([self.load_3byte() for i in range(num)], ) - elif argspec == "varargs": - args += (self.load_varargs(), ) - elif argspec == "constargs": - args += (self.load_constargs(), ) - elif argspec == "descr": - descr = self.load_const_arg() - assert isinstance(descr, history.AbstractDescr) - args += (descr, ) - elif argspec == "bytecode": - bytecode = self.load_const_arg() - assert isinstance(bytecode, codewriter.JitCode) - args += (bytecode, ) - elif argspec == "orgpc": - args += (orgpc, ) - elif argspec == "methdescr": - methdescr = self.load_const_arg() - assert isinstance(methdescr, - history.AbstractMethDescr) - args += (methdescr, ) - else: - assert 0, "unknown argtype declaration: %r" % (argspec,) - val = func(*args) - if val is None: - val = False - return val - name = func.func_name - wrapped.func_name = "wrap_" + name - wrapped.argspec = self - return wrapped +def arguments(*args): + def decorate(func): + func.argtypes = args + return func + return decorate # ____________________________________________________________ class MIFrame(object): - exception_box = None - exc_value_box = None - # for resume.py operation - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - def __init__(self, metainterp, jitcode, greenkey=None): - assert isinstance(jitcode, codewriter.JitCode) + def __init__(self, metainterp): self.metainterp = metainterp + self.registers_i = [None] * 256 + self.registers_r = [None] * 256 + self.registers_f = [None] * 256 + + def setup(self, jitcode, greenkey=None): + assert isinstance(jitcode, JitCode) self.jitcode = jitcode self.bytecode = jitcode.code - self.constants = jitcode.constants - self.exception_target = -1 - self.name = jitcode.name # purely for having name attribute # this is not None for frames that are recursive portal calls self.greenkey = greenkey + # copy the constants in place + self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt) + self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr) + self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat) + self._result_argcode = 'v' + # for resume.py operation + self.parent_resumedata_snapshot = None + self.parent_resumedata_frame_info_list = None + + def copy_constants(self, registers, constants, ConstClass): + """Copy jitcode.constants[0] to registers[255], + jitcode.constants[1] to registers[254], + jitcode.constants[2] to registers[253], etc.""" + if nonconst.NonConstant(0): # force the right type + constants[0] = ConstClass.value # (useful for small tests) + i = len(constants) - 1 + while i >= 0: + j = 255 - i + assert j >= 0 + registers[j] = ConstClass(constants[i]) + i -= 1 + copy_constants._annspecialcase_ = 'specialize:arg(3)' + + def cleanup_registers(self): + # To avoid keeping references alive, this cleans up the registers_r. + # It does not clear the references set by copy_constants(), but + # these are all prebuilt constants anyway. + for i in range(self.jitcode.num_regs_r()): + self.registers_r[i] = None # ------------------------------ # Decoding of the JitCode - def load_int(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - if result > 0x7F: - result = self._load_larger_int(result) - return result - - def _load_larger_int(self, result): # slow path - result = result & 0x7F - shift = 7 - pc = self.pc - while 1: - byte = ord(self.bytecode[pc]) - pc += 1 - result += (byte & 0x7F) << shift - shift += 7 - if not byte & 0x80: - break - self.pc = pc - return intmask(result) - _load_larger_int._dont_inline_ = True - - def load_3byte(self): - pc = self.pc - result = (((ord(self.bytecode[pc + 0])) << 16) | - ((ord(self.bytecode[pc + 1])) << 8) | - ((ord(self.bytecode[pc + 2])) << 0)) - self.pc = pc + 3 - return result - - def load_bool(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - return bool(result) - - def getenv(self, i): - assert i >= 0 - j = i >> 1 - if i & 1: - return self.constants[j] - else: - assert j < len(self.env) - return self.env[j] - - def load_arg(self): - return self.getenv(self.load_int()) - - def load_const_arg(self): - return self.constants[self.load_int()] - - def load_varargs(self): - count = self.load_int() - return [self.load_arg() for i in range(count)] - - def load_constargs(self): - count = self.load_int() - return [self.load_const_arg() for i in range(count)] - - def ignore_varargs(self): - count = self.load_int() + def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): + assert argcode in 'IRF' + code = self.bytecode + length = ord(code[position]) + position += 1 + for i in range(length): + index = ord(code[position+i]) + if argcode == 'I': reg = self.registers_i[index] + elif argcode == 'R': reg = self.registers_r[index] + elif argcode == 'F': reg = self.registers_f[index] + else: raise AssertionError(argcode) + outvalue[startindex+i] = reg + prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' + + def get_current_position_info(self): + return self.jitcode.get_live_vars_info(self.pc) + + def get_list_of_active_boxes(self, in_a_call): + if in_a_call: + # If we are not the topmost frame, self._result_argcode contains + # the type of the result of the call instruction in the bytecode. + # We use it to clear the box that will hold the result: this box + # is not defined yet. + argcode = self._result_argcode + index = ord(self.bytecode[self.pc - 1]) + if argcode == 'i': self.registers_i[index] = history.CONST_FALSE + elif argcode == 'r': self.registers_r[index] = history.CONST_NULL + elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO + self._result_argcode = '?' # done + # + info = self.get_current_position_info() + start_i = 0 + start_r = start_i + info.get_register_count_i() + start_f = start_r + info.get_register_count_r() + total = start_f + info.get_register_count_f() + # allocate a list of the correct size + env = [None] * total + make_sure_not_resized(env) + # fill it now + for i in range(info.get_register_count_i()): + index = info.get_register_index_i(i) + env[start_i + i] = self.registers_i[index] + for i in range(info.get_register_count_r()): + index = info.get_register_index_r(i) + env[start_r + i] = self.registers_r[index] + for i in range(info.get_register_count_f()): + index = info.get_register_index_f(i) + env[start_f + i] = self.registers_f[index] + return env + + def replace_active_box_in_frame(self, oldbox, newbox): + if isinstance(oldbox, history.BoxInt): + count = self.jitcode.num_regs_i() + registers = self.registers_i + elif isinstance(oldbox, history.BoxPtr): + count = self.jitcode.num_regs_r() + registers = self.registers_r + elif isinstance(oldbox, history.BoxFloat): + count = self.jitcode.num_regs_f() + registers = self.registers_f + else: + assert 0, oldbox for i in range(count): - self.load_int() - - def getvarenv(self, i): - return self.env[i] + if registers[i] is oldbox: + registers[i] = newbox + if not we_are_translated(): + assert oldbox not in registers[count:] - def make_result_box(self, box): - assert isinstance(box, Box) or isinstance(box, Const) - self.env.append(box) + def make_result_of_lastop(self, resultbox): + if resultbox is None: + return + target_index = ord(self.bytecode[self.pc-1]) + if resultbox.type == history.INT: + self.registers_i[target_index] = resultbox + elif resultbox.type == history.REF: + #debug_print(' ->', + # llmemory.cast_ptr_to_adr(resultbox.getref_base())) + self.registers_r[target_index] = resultbox + elif resultbox.type == history.FLOAT: + self.registers_f[target_index] = resultbox + else: + raise AssertionError("bad result box type") # ------------------------------ - for _n in range(codewriter.MAX_MAKE_NEW_VARS): - _decl = ', '.join(["'box'" for _i in range(_n)]) - _allargs = ', '.join(["box%d" % _i for _i in range(_n)]) - exec py.code.Source(""" - @arguments(%s) - def opimpl_make_new_vars_%d(self, %s): - if not we_are_translated(): - check_args(%s) - self.env = [%s] - """ % (_decl, _n, _allargs, _allargs, _allargs)).compile() - - @arguments("varargs") - def opimpl_make_new_vars(self, newenv): - if not we_are_translated(): - check_args(*newenv) - self.env = newenv - for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod', 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', @@ -210,175 +175,241 @@ 'float_add', 'float_sub', 'float_mul', 'float_truediv', 'float_lt', 'float_le', 'float_eq', 'float_ne', 'float_gt', 'float_ge', + 'ptr_eq', 'ptr_ne', ]: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) + return self.execute(rop.%s, b1, b2) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) - return self.metainterp.handle_overflow_error() + self.metainterp.clear_exception() + resbox = self.execute(rop.%s, b1, b2) + self.make_result_of_lastop(resbox) # same as execute_varargs() + self.metainterp.handle_possible_overflow_error() + return resbox ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', - 'cast_ptr_to_int', 'cast_float_to_int', - 'cast_int_to_float', 'float_neg', 'float_abs', - 'float_is_true', + for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert', + 'cast_float_to_int', 'cast_int_to_float', + 'float_neg', 'float_abs', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, b) + return self.execute(rop.%s, b) ''' % (_opimpl, _opimpl.upper())).compile() - @arguments() - def opimpl_return(self): - assert len(self.env) == 1 - return self.metainterp.finishframe(self.env[0]) + @arguments("box") + def opimpl_ptr_nonzero(self, box): + return self.execute(rop.PTR_NE, box, history.CONST_NULL) + + @arguments("box") + def opimpl_ptr_iszero(self, box): + return self.execute(rop.PTR_EQ, box, history.CONST_NULL) + + @arguments("box") + def _opimpl_any_return(self, box): + self.metainterp.finishframe(box) + + opimpl_int_return = _opimpl_any_return + opimpl_ref_return = _opimpl_any_return + opimpl_float_return = _opimpl_any_return @arguments() def opimpl_void_return(self): - assert len(self.env) == 0 - return self.metainterp.finishframe(None) + self.metainterp.finishframe(None) + + @arguments("box") + def _opimpl_any_copy(self, box): + return box + + opimpl_int_copy = _opimpl_any_copy + opimpl_ref_copy = _opimpl_any_copy + opimpl_float_copy = _opimpl_any_copy + + @arguments("box") + def _opimpl_any_push(self, box): + self.pushed_box = box + + opimpl_int_push = _opimpl_any_push + opimpl_ref_push = _opimpl_any_push + opimpl_float_push = _opimpl_any_push - @arguments("jumptarget") + @arguments() + def _opimpl_any_pop(self): + box = self.pushed_box + self.pushed_box = None + return box + + opimpl_int_pop = _opimpl_any_pop + opimpl_ref_pop = _opimpl_any_pop + opimpl_float_pop = _opimpl_any_pop + + @arguments("label") + def opimpl_catch_exception(self, target): + """This is a no-op when run normally. We can check that + last_exc_value_box is None; it should have been set to None + by the previous instruction. If the previous instruction + raised instead, finishframe_exception() should have been + called and we would not be there.""" + assert self.metainterp.last_exc_value_box is None + + @arguments("label") def opimpl_goto(self, target): self.pc = target - @arguments("orgpc", "jumptarget", "box", "varargs") - def opimpl_goto_if_not(self, pc, target, box, livelist): + @arguments("box", "label") + def opimpl_goto_if_not(self, box, target): switchcase = box.getint() if switchcase: opnum = rop.GUARD_TRUE else: - self.pc = target opnum = rop.GUARD_FALSE - self.env = livelist - self.generate_guard(pc, opnum, box) - # note about handling self.env explicitly here: it is done in - # such a way that the 'box' on which we generate the guard is - # typically not included in the livelist. - - def follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - target = self.load_3byte() # load the 'target' argument - self.pc = target # jump - - def ignore_next_guard_nullness(self, opnum): - _op_ooisnull = self.metainterp.staticdata._op_ooisnull - _op_oononnull = self.metainterp.staticdata._op_oononnull - bc = ord(self.bytecode[self.pc]) - if bc == _op_ooisnull: - if opnum == rop.GUARD_ISNULL: - res = ConstInt(0) - else: - res = ConstInt(1) + self.generate_guard(opnum, box) + if not switchcase: + self.pc = target + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_true(self, box, target): + condbox = self.execute(rop.INT_IS_TRUE, box) + self.opimpl_goto_if_not(condbox, target) + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_zero(self, box, target): + condbox = self.execute(rop.INT_IS_ZERO, box) + self.opimpl_goto_if_not(condbox, target) + + for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', + 'ptr_eq', 'ptr_ne']: + exec py.code.Source(''' + @arguments("box", "box", "label") + def opimpl_goto_if_not_%s(self, b1, b2, target): + condbox = self.execute(rop.%s, b1, b2) + self.opimpl_goto_if_not(condbox, target) + ''' % (_opimpl, _opimpl.upper())).compile() + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL else: - assert bc == _op_oononnull - if opnum == rop.GUARD_ISNULL: - res = ConstInt(1) - else: - res = ConstInt(0) - self.pc += 1 # past the bytecode for ptr_iszero/ptr_nonzero - self.load_int() # past the 'box' argument - self.make_result_box(res) - - def dont_follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - self.load_3byte() # past the 'target' argument - self.load_int() # past the 'box' argument - self.ignore_varargs() # past the 'livelist' argument - - @arguments("orgpc", "box", "constargs", "jumptargets") - def opimpl_switch(self, pc, valuebox, constargs, jumptargets): - box = self.implement_guard_value(pc, valuebox) - for i in range(len(constargs)): - casebox = constargs[i] - if box.same_constant(casebox): - self.pc = jumptargets[i] - break - - @arguments("orgpc", "box", "constbox") - def opimpl_switch_dict(self, pc, valuebox, switchdict): - box = self.implement_guard_value(pc, valuebox) + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if not value: + self.pc = target + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL + else: + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if value: + self.pc = target + + @arguments("box", "descr", "orgpc") + def opimpl_switch(self, valuebox, switchdict, orgpc): + box = self.implement_guard_value(orgpc, valuebox) search_value = box.getint() - assert isinstance(switchdict, codewriter.SwitchDict) + assert isinstance(switchdict, SwitchDictDescr) try: self.pc = switchdict.dict[search_value] except KeyError: pass - @arguments("descr") - def opimpl_new(self, size): - self.execute_with_descr(rop.NEW, descr=size) - - @arguments("constbox") - def opimpl_new_with_vtable(self, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, vtablebox) + @arguments() + def opimpl_unreachable(self): + raise AssertionError("unreachable") - @arguments("box") - def opimpl_runtimenew(self, classbox): - self.execute(rop.RUNTIMENEW, classbox) + @arguments("descr") + def opimpl_new(self, sizedescr): + return self.execute_with_descr(rop.NEW, sizedescr) - @arguments("orgpc", "box", "descr") - def opimpl_instanceof(self, pc, objbox, typedescr): - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + @arguments("descr") + def opimpl_new_with_vtable(self, sizedescr): + cpu = self.metainterp.cpu + cls = heaptracker.descr2vtable(cpu, sizedescr) + return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls)) - @arguments("box", "box") - def opimpl_subclassof(self, box1, box2): - self.execute(rop.SUBCLASSOF, box1, box2) +## @FixME #arguments("box") +## def opimpl_runtimenew(self, classbox): +## self.execute(rop.RUNTIMENEW, classbox) + +## @FixME #arguments("orgpc", "box", "descr") +## def opimpl_instanceof(self, pc, objbox, typedescr): +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + +## @FixME #arguments("box", "box") +## def opimpl_subclassof(self, box1, box2): +## self.execute(rop.SUBCLASSOF, box1, box2) @arguments("descr", "box") - def opimpl_new_array(self, itemsize, countbox): - self.execute_with_descr(rop.NEW_ARRAY, itemsize, countbox) + def opimpl_new_array(self, itemsizedescr, countbox): + return self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, countbox) @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_pure_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_pure_i = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_r = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_f = _opimpl_getarrayitem_gc_pure_any @arguments("box", "descr", "box", "box") - def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydesc, arraybox, indexbox, itembox) + def _opimpl_setarrayitem_gc_any(self, arraybox, arraydescr, + indexbox, itembox): + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, itembox) + + opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any @arguments("box", "descr") - def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute_with_descr(rop.ARRAYLEN_GC, arraydesc, arraybox) + def opimpl_arraylen_gc(self, arraybox, arraydescr): + return self.execute_with_descr(rop.ARRAYLEN_GC, arraydescr, arraybox) @arguments("descr", "box", "box", "box", "box", "box", "box", "descr") def opimpl_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): + source_startbox, dest_startbox, lengthbox, + arraydescr): self.execute_with_descr(rop.ARRAYCOPY, arraydescr, calldescr, fnptr, sourcebox, destbox, source_startbox, dest_startbox, lengthbox) @arguments("orgpc", "box", "descr", "box") - def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): + def opimpl_check_neg_index(self, orgpc, arraybox, arraydescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, arraydesc, arraybox) + rop.ARRAYLEN_GC, arraydescr, arraybox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) + return indexbox @arguments("descr", "descr", "descr", "descr", "box") def opimpl_newlist(self, structdescr, lengthdescr, itemsdescr, arraydescr, @@ -390,131 +421,87 @@ sizebox) self.metainterp.execute_and_record(rop.SETFIELD_GC, itemsdescr, sbox, abox) - self.make_result_box(sbox) + return sbox @arguments("box", "descr", "descr", "box") - def opimpl_getlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox): + def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydescr, arraybox, indexbox) + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any @arguments("box", "descr", "descr", "box", "box") - def opimpl_setlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox, - valuebox): + def _opimpl_setlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox, valuebox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, indexbox, valuebox) + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, valuebox) + + opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any @arguments("orgpc", "box", "descr", "box") - def opimpl_check_resizable_neg_index(self, pc, listbox, lengthdesc, + def opimpl_check_resizable_neg_index(self, orgpc, listbox, lengthdescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.GETFIELD_GC, lengthdesc, listbox) + rop.GETFIELD_GC, lengthdescr, listbox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) - - @arguments("orgpc", "box") - def opimpl_check_zerodivisionerror(self, pc, box): - nonzerobox = self.metainterp.execute_and_record( - rop.INT_NE, None, box, ConstInt(0)) - nonzerobox = self.implement_guard_value(pc, nonzerobox) - if nonzerobox.getint(): - return False - else: - # division by zero! - return self.metainterp.raise_zero_division_error() - - @arguments("orgpc", "box", "box") - def opimpl_check_div_overflow(self, pc, box1, box2): - # detect the combination "box1 = -sys.maxint-1, box2 = -1". - import sys - tmp1 = self.metainterp.execute_and_record( # combination to detect: - rop.INT_ADD, None, box1, ConstInt(sys.maxint)) # tmp1=-1, box2=-1 - tmp2 = self.metainterp.execute_and_record( - rop.INT_AND, None, tmp1, box2) # tmp2=-1 - tmp3 = self.metainterp.execute_and_record( - rop.INT_EQ, None, tmp2, ConstInt(-1)) # tmp3? - tmp4 = self.implement_guard_value(pc, tmp3) # tmp4? - if not tmp4.getint(): - return False - else: - # division overflow! - return self.metainterp.raise_overflow_error() - - @arguments() - def opimpl_overflow_error(self): - return self.metainterp.raise_overflow_error() - - @arguments("orgpc", "box") - def opimpl_int_abs(self, pc, box): - nonneg = self.metainterp.execute_and_record( - rop.INT_GE, None, box, ConstInt(0)) - nonneg = self.implement_guard_value(pc, nonneg) - if nonneg.getint(): - self.make_result_box(box) - else: - self.execute(rop.INT_NEG, box) - - @arguments("orgpc", "box") - def opimpl_oononnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(1) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(0) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("orgpc", "box") - def opimpl_ooisnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(0) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(1) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("box", "box") - def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, box1, box2) - - @arguments("box", "box") - def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, box1, box2) - - opimpl_oois = opimpl_ptr_eq - opimpl_ooisnot = opimpl_ptr_ne + return indexbox @arguments("box", "descr") - def opimpl_getfield_gc(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC, fielddesc, box) + def _opimpl_getfield_gc_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) + opimpl_getfield_gc_i = _opimpl_getfield_gc_any + opimpl_getfield_gc_r = _opimpl_getfield_gc_any + opimpl_getfield_gc_f = _opimpl_getfield_gc_any + @arguments("box", "descr") - def opimpl_getfield_gc_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddesc, box) + def _opimpl_getfield_gc_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box) + opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_GC, fielddesc, box, valuebox) + def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) + opimpl_setfield_gc_i = _opimpl_setfield_gc_any + opimpl_setfield_gc_r = _opimpl_setfield_gc_any + opimpl_setfield_gc_f = _opimpl_setfield_gc_any @arguments("box", "descr") - def opimpl_getfield_raw(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW, fielddesc, box) + def _opimpl_getfield_raw_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box) + opimpl_getfield_raw_i = _opimpl_getfield_raw_any + opimpl_getfield_raw_r = _opimpl_getfield_raw_any + opimpl_getfield_raw_f = _opimpl_getfield_raw_any + @arguments("box", "descr") - def opimpl_getfield_raw_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddesc, box) + def _opimpl_getfield_raw_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box) + opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_RAW, fielddesc, box, valuebox) + def _opimpl_setfield_raw_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox) + opimpl_setfield_raw_i = _opimpl_setfield_raw_any + opimpl_setfield_raw_r = _opimpl_setfield_raw_any + opimpl_setfield_raw_f = _opimpl_setfield_raw_any def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable @@ -522,7 +509,7 @@ standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False - eqbox = self.metainterp.execute_and_record(rop.OOIS, None, + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, box, standard_box) eqbox = self.implement_guard_value(pc, eqbox) isstandard = eqbox.getint() @@ -530,9 +517,9 @@ self.metainterp.replace_box(box, standard_box) return not isstandard - def _get_virtualizable_field_descr(self, index): + def _get_virtualizable_field_index(self, fielddescr): vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.static_field_descrs[index] + return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): vinfo = self.metainterp.staticdata.virtualizable_info @@ -542,328 +529,271 @@ vinfo = self.metainterp.staticdata.virtualizable_info return vinfo.array_descrs[index] - @arguments("orgpc", "box", "int") - def opimpl_getfield_vable(self, pc, basebox, index): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.GETFIELD_GC, self._get_virtualizable_field_descr(index), basebox) - return + @arguments("orgpc", "box", "descr") + def _opimpl_getfield_vable(self, pc, box, fielddescr): + if self._nonstandard_virtualizable(pc, box): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) self.metainterp.check_synchronized_virtualizable() - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box") - def opimpl_setfield_vable(self, pc, basebox, index, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.SETFIELD_GC, self._get_virtualizable_field_descr(index), basebox, valuebox) + index = self._get_virtualizable_field_index(fielddescr) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getfield_vable_i = _opimpl_getfield_vable + opimpl_getfield_vable_r = _opimpl_getfield_vable + opimpl_getfield_vable_f = _opimpl_getfield_vable + + @arguments("orgpc", "box", "descr", "box") + def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox): + if self._nonstandard_virtualizable(pc, box): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) return + index = self._get_virtualizable_field_index(fielddescr) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - def _get_arrayitem_vable_index(self, pc, arrayindex, indexbox): + opimpl_setfield_vable_i = _opimpl_setfield_vable + opimpl_setfield_vable_r = _opimpl_setfield_vable + opimpl_setfield_vable_f = _opimpl_setfield_vable + + def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] index = indexbox.getint() if index < 0: index += vinfo.get_array_length(virtualizable, arrayindex) assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex) return vinfo.get_index_in_array(virtualizable, arrayindex, index) - @arguments("orgpc", "box", "int", "box") - def opimpl_getarrayitem_vable(self, pc, basebox, arrayindex, indexbox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + @arguments("orgpc", "box", "descr", "descr", "box") + def _opimpl_getarrayitem_vable(self, pc, box, fdescr, adescr, indexbox): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.GETARRAYITEM_GC, descr, - arraybox, indexbox) - return + fdescr, box) + return self.execute_with_descr(rop.GETARRAYITEM_GC, adescr, + arraybox, indexbox) self.metainterp.check_synchronized_virtualizable() - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box", "box") - def opimpl_setarrayitem_vable(self, pc, basebox, arrayindex, indexbox, + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr", "box", "box") + def _opimpl_setarrayitem_vable(self, pc, box, fdescr, adescr, indexbox, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.SETARRAYITEM_GC, descr, + fdescr, box) + self.execute_with_descr(rop.SETARRAYITEM_GC, adescr, arraybox, indexbox, valuebox) return - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - @arguments("orgpc", "box", "int") - def opimpl_arraylen_vable(self, pc, basebox, arrayindex): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + + opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr") + def opimpl_arraylen_vable(self, pc, box, fdescr, adescr): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.ARRAYLEN_GC, descr, arraybox) - return + fdescr, box) + return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[fdescr] result = vinfo.get_array_length(virtualizable, arrayindex) - self.make_result_box(ConstInt(result)) + return ConstInt(result) - def perform_call(self, jitcode, varargs, greenkey=None): - if (self.metainterp.is_blackholing() and - jitcode.calldescr is not None): - # when producing only a BlackHole, we can implement this by - # calling the subfunction directly instead of interpreting it - if jitcode.cfnptr is not None: - # for non-oosends - varargs = [jitcode.cfnptr] + varargs - res = self.execute_varargs(rop.CALL, varargs, - descr=jitcode.calldescr, exc=True) - else: - # for oosends (ootype only): calldescr is a MethDescr - res = self.execute_varargs(rop.OOSEND, varargs, - descr=jitcode.calldescr, exc=True) - self.metainterp.load_fields_from_virtualizable() - return res - else: - # when tracing, this bytecode causes the subfunction to be entered - f = self.metainterp.newframe(jitcode, greenkey) - f.setup_call(varargs) - return True - - @arguments("bytecode", "varargs") - def opimpl_call(self, callee, varargs): - return self.perform_call(callee, varargs) - - @arguments("descr", "varargs") - def opimpl_residual_call(self, calldescr, varargs): - return self.do_residual_call(varargs, descr=calldescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_call_loopinvariant(self, calldescr, varargs): - return self.execute_varargs(rop.CALL_LOOPINVARIANT, varargs, calldescr, exc=True) - - @arguments("orgpc", "descr", "varargs") - def opimpl_recursive_call(self, pc, calldescr, varargs): - warmrunnerstate = self.metainterp.staticdata.state + @arguments("jitcode", "boxes") + def _opimpl_inline_call1(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes2") + def _opimpl_inline_call2(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes3") + def _opimpl_inline_call3(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + + opimpl_inline_call_r_i = _opimpl_inline_call1 + opimpl_inline_call_r_r = _opimpl_inline_call1 + opimpl_inline_call_r_v = _opimpl_inline_call1 + opimpl_inline_call_ir_i = _opimpl_inline_call2 + opimpl_inline_call_ir_r = _opimpl_inline_call2 + opimpl_inline_call_ir_v = _opimpl_inline_call2 + opimpl_inline_call_irf_i = _opimpl_inline_call3 + opimpl_inline_call_irf_r = _opimpl_inline_call3 + opimpl_inline_call_irf_f = _opimpl_inline_call3 + opimpl_inline_call_irf_v = _opimpl_inline_call3 + + @arguments("box", "descr", "boxes") + def _opimpl_residual_call1(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes2") + def _opimpl_residual_call2(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes3") + def _opimpl_residual_call3(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + + opimpl_residual_call_r_i = _opimpl_residual_call1 + opimpl_residual_call_r_r = _opimpl_residual_call1 + opimpl_residual_call_r_v = _opimpl_residual_call1 + opimpl_residual_call_ir_i = _opimpl_residual_call2 + opimpl_residual_call_ir_r = _opimpl_residual_call2 + opimpl_residual_call_ir_v = _opimpl_residual_call2 + opimpl_residual_call_irf_i = _opimpl_residual_call3 + opimpl_residual_call_irf_r = _opimpl_residual_call3 + opimpl_residual_call_irf_f = _opimpl_residual_call3 + opimpl_residual_call_irf_v = _opimpl_residual_call3 + + @arguments("boxes3", "boxes3") + def _opimpl_recursive_call(self, greenboxes, redboxes): + allboxes = greenboxes + redboxes + metainterp_sd = self.metainterp.staticdata + portal_code = metainterp_sd.portal_code + warmrunnerstate = metainterp_sd.state token = None - if not self.metainterp.is_blackholing() and warmrunnerstate.inlining: - num_green_args = self.metainterp.staticdata.num_green_args - portal_code = self.metainterp.staticdata.portal_code - greenkey = varargs[1:num_green_args + 1] - if warmrunnerstate.can_inline_callable(greenkey): - return self.perform_call(portal_code, varargs[1:], greenkey) - token = warmrunnerstate.get_assembler_token(greenkey) - call_position = 0 - if token is not None: - call_position = len(self.metainterp.history.operations) + if warmrunnerstate.inlining: + if warmrunnerstate.can_inline_callable(greenboxes): + return self.metainterp.perform_call(portal_code, allboxes, + greenkey=greenboxes) + token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - greenargs = varargs[1:num_green_args + 1] - self.verify_green_args(greenargs) - res = self.do_residual_call(varargs, descr=calldescr, exc=True) - if not self.metainterp.is_blackholing() and token is not None: - # XXX fix the call position, - found = False - while True: - op = self.metainterp.history.operations[call_position] - if op.opnum == rop.CALL or op.opnum == rop.CALL_MAY_FORCE: - found = True - break - call_position += 1 - assert found - # - # this will substitute the residual call with assembler call - self.metainterp.direct_assembler_call(pc, varargs, token, - call_position) - return res - - @arguments("descr", "varargs") - def opimpl_residual_call_noexception(self, calldescr, varargs): - self.do_residual_call(varargs, descr=calldescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_call_pure(self, calldescr, varargs): - self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False) - - @arguments("orgpc", "descr", "box", "varargs") - def opimpl_indirect_call(self, pc, calldescr, box, varargs): - box = self.implement_guard_value(pc, box) - cpu = self.metainterp.cpu - key = cpu.ts.getaddr_for_box(cpu, box) - jitcode = self.metainterp.staticdata.bytecode_for_address(key) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.do_residual_call([box] + varargs, - descr=calldescr, exc=True) - - @arguments("orgpc", "methdescr", "varargs") - def opimpl_oosend(self, pc, methdescr, varargs): - objbox = varargs[0] - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - oocls = clsbox.getref(ootype.Class) - jitcode = methdescr.get_jitcode_for_class(oocls) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.execute_varargs(rop.OOSEND, varargs, - descr=methdescr, exc=True) + self.verify_green_args(greenboxes) + # + k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + funcbox = ConstInt(heaptracker.adr2int(k)) + return self.do_residual_call(funcbox, portal_code.calldescr, + allboxes, assembler_call_token=token) + + opimpl_recursive_call_i = _opimpl_recursive_call + opimpl_recursive_call_r = _opimpl_recursive_call + opimpl_recursive_call_f = _opimpl_recursive_call + opimpl_recursive_call_v = _opimpl_recursive_call + +## @FixME #arguments("orgpc", "methdescr", "varargs") +## def opimpl_oosend(self, pc, methdescr, varargs): +## objbox = varargs[0] +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## oocls = clsbox.getref(ootype.Class) +## jitcode = methdescr.get_jitcode_for_class(oocls) +## if jitcode is not None: +## # we should follow calls to this graph +## return self.perform_call(jitcode, varargs) +## else: +## # but we should not follow calls to that graph +## return self.execute_varargs(rop.OOSEND, varargs, +## descr=methdescr, exc=True) @arguments("box") - def opimpl_strlen(self, str): - self.execute(rop.STRLEN, str) + def opimpl_strlen(self, strbox): + return self.execute(rop.STRLEN, strbox) @arguments("box") - def opimpl_unicodelen(self, str): - self.execute(rop.UNICODELEN, str) + def opimpl_unicodelen(self, unicodebox): + return self.execute(rop.UNICODELEN, unicodebox) @arguments("box", "box") - def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, str, index) + def opimpl_strgetitem(self, strbox, indexbox): + return self.execute(rop.STRGETITEM, strbox, indexbox) @arguments("box", "box") - def opimpl_unicodegetitem(self, str, index): - self.execute(rop.UNICODEGETITEM, str, index) + def opimpl_unicodegetitem(self, unicodebox, indexbox): + return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox) @arguments("box", "box", "box") - def opimpl_strsetitem(self, str, index, newchar): - self.execute(rop.STRSETITEM, str, index, newchar) + def opimpl_strsetitem(self, strbox, indexbox, newcharbox): + return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox) @arguments("box", "box", "box") - def opimpl_unicodesetitem(self, str, index, newchar): - self.execute(rop.UNICODESETITEM, str, index, newchar) + def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox): + self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox) @arguments("box") - def opimpl_newstr(self, length): - self.execute(rop.NEWSTR, length) + def opimpl_newstr(self, lengthbox): + return self.execute(rop.NEWSTR, lengthbox) @arguments("box") - def opimpl_newunicode(self, length): - self.execute(rop.NEWUNICODE, length) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_canraise(self, methdescr, varargs): - return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_noraise(self, methdescr, varargs): - self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_pure(self, methdescr, boxes): - self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, exc=False) + def opimpl_newunicode(self, lengthbox): + return self.execute(rop.NEWUNICODE, lengthbox) - @arguments("orgpc", "box") - def opimpl_guard_value(self, pc, box): - constbox = self.implement_guard_value(pc, box) - self.make_result_box(constbox) - - @arguments("orgpc", "int") - def opimpl_guard_green(self, pc, boxindex): - """Like guard_value, but overwrites the original box with the const. - Used to prevent Boxes from showing up in the greenkey of some - operations, like jit_merge_point. The in-place overwriting is - convenient for jit_merge_point, which expects self.env to contain - not more than the greens+reds described in the jitdriver.""" - box = self.env[boxindex] - constbox = self.implement_guard_value(pc, box) - self.env[boxindex] = constbox +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_canraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=True) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_noraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=False) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_pure(self, methdescr, boxes): +## return self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, +## exc=False) + + @arguments("orgpc", "box",) + def _opimpl_guard_value(self, orgpc, box): + self.implement_guard_value(orgpc, box) + + opimpl_int_guard_value = _opimpl_guard_value + opimpl_ref_guard_value = _opimpl_guard_value + opimpl_float_guard_value = _opimpl_guard_value @arguments("orgpc", "box") - def opimpl_guard_class(self, pc, box): + def opimpl_guard_class(self, orgpc, box): clsbox = self.cls_of_box(box) - if isinstance(box, Box): - self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) - self.make_result_box(clsbox) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_builtin(self, pc, box, builtin): -## self.generate_guard(pc, "guard_builtin", box, [builtin]) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_len(self, pc, box, builtin): -## intbox = self.metainterp.cpu.execute_operation( -## 'len', [builtin.len_func, box], 'int') -## self.generate_guard(pc, "guard_len", box, [intbox]) - - @arguments("box") - def opimpl_keepalive(self, box): - pass # xxx? - - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args - for i in range(num_green_args): - assert isinstance(varargs[i], Const) - - def blackhole_reached_merge_point(self, varargs): - if self.metainterp.in_recursion: - portal_code = self.metainterp.staticdata.portal_code - # small hack: fish for the result box - lenenv = len(self.env) - raised = self.perform_call(portal_code, varargs) - # in general this cannot be assumed, but when blackholing, - # perform_call returns True only if an exception is called. In - # this case perform_call has called finishframe_exception - # already, so we need to return. - if raised: - return - if lenenv == len(self.env): - res = None - else: - assert lenenv == len(self.env) - 1 - res = self.env.pop() - self.metainterp.finishframe(res) - else: - raise self.metainterp.staticdata.ContinueRunningNormally(varargs) + self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + return clsbox @arguments() def opimpl_can_enter_jit(self): - # Note: when running with a BlackHole history, this 'can_enter_jit' - # may be completely skipped by the logic that replaces perform_call - # with rop.CALL. But in that case, no-one will check the flag anyway, - # so it's fine. if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - @arguments() - def opimpl_jit_merge_point(self): - if not self.metainterp.is_blackholing(): - self.verify_green_args(self.env) - # xxx we may disable the following line in some context later - self.debug_merge_point() - if self.metainterp.seen_can_enter_jit: - self.metainterp.seen_can_enter_jit = False - assert not self.metainterp.in_recursion - # ^^^ it's impossible to arrive here with in_recursion set - # to a non-zero value: seen_can_enter_jit can only be set - # to True by opimpl_can_enter_jit, which should be executed - # just before opimpl_jit_merge_point (no recursion inbetween). - try: - self.metainterp.reached_can_enter_jit(self.env) - except GiveUp: - self.metainterp.switch_to_blackhole(ABORT_BRIDGE) - if self.metainterp.is_blackholing(): - self.blackhole_reached_merge_point(self.env) - return True + def verify_green_args(self, varargs): + num_green_args = self.metainterp.staticdata.num_green_args + assert len(varargs) == num_green_args + for i in range(num_green_args): + assert isinstance(varargs[i], Const) - def debug_merge_point(self): + @arguments("orgpc", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): + self.verify_green_args(greenboxes) + # xxx we may disable the following line in some context later + self.debug_merge_point(greenboxes) + if self.metainterp.seen_can_enter_jit: + self.metainterp.seen_can_enter_jit = False + # Assert that it's impossible to arrive here with in_recursion + # set to a non-zero value: seen_can_enter_jit can only be set + # to True by opimpl_can_enter_jit, which should be executed + # just before opimpl_jit_merge_point (no recursion inbetween). + assert not self.metainterp.in_recursion + # Set self.pc to point to jit_merge_point instead of just after: + # if reached_can_enter_jit() raises SwitchToBlackhole, then the + # pc is still at the jit_merge_point, which is a point that is + # much less expensive to blackhole out of. + saved_pc = self.pc + self.pc = orgpc + self.metainterp.reached_can_enter_jit(greenboxes, redboxes) + self.pc = saved_pc + + def debug_merge_point(self, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - num_green_args = self.metainterp.staticdata.num_green_args - greenkey = self.env[:num_green_args] sd = self.metainterp.staticdata loc = sd.state.get_location_str(greenkey) debug_print(loc) @@ -871,45 +801,45 @@ self.metainterp.history.record(rop.DEBUG_MERGE_POINT, [constloc], None) - @arguments("jumptarget") - def opimpl_setup_exception_block(self, exception_target): - self.exception_target = exception_target - - @arguments() - def opimpl_teardown_exception_block(self): - self.exception_target = -1 - - @arguments("constbox", "jumptarget", "orgpc") - def opimpl_goto_if_exception_mismatch(self, vtableref, next_exc_target, pc): - # XXX used to be: - # assert isinstance(self.exception_box, Const) # XXX - # seems this can happen that self.exception_box is not a Const, - # but I failed to write a test so far :-( - self.exception_box = self.implement_guard_value(pc, self.exception_box) - cpu = self.metainterp.cpu - ts = self.metainterp.cpu.ts - if not ts.subclassOf(cpu, self.exception_box, vtableref): + @arguments("box", "label") + def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target): + metainterp = self.metainterp + last_exc_value_box = metainterp.last_exc_value_box + assert last_exc_value_box is not None + assert metainterp.class_of_last_exc_is_const + if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox): self.pc = next_exc_target - @arguments("int") - def opimpl_put_last_exception(self, index): - assert index >= 0 - self.env.insert(index, self.exception_box) - - @arguments("int") - def opimpl_put_last_exc_value(self, index): - assert index >= 0 - self.env.insert(index, self.exc_value_box) + @arguments("orgpc", "box") + def opimpl_raise(self, orgpc, exc_value_box): + # xxx hack + clsbox = self.cls_of_box(exc_value_box) + self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + resumepc=orgpc) + self.metainterp.class_of_last_exc_is_const = True + self.metainterp.last_exc_value_box = exc_value_box + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_raise(self): - assert len(self.env) == 2 - return self.metainterp.finishframe_exception(self.env[0], self.env[1]) + def opimpl_reraise(self): + assert self.metainterp.last_exc_value_box is not None + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_reraise(self): - return self.metainterp.finishframe_exception(self.exception_box, - self.exc_value_box) + def opimpl_last_exception(self): + # Same comment as in opimpl_goto_if_exception_mismatch(). + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + assert self.metainterp.class_of_last_exc_is_const + return self.metainterp.cpu.ts.cls_of_box(exc_value_box) + + @arguments() + def opimpl_last_exc_value(self): + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + return exc_value_box @arguments("box") def opimpl_virtual_ref(self, box): @@ -920,30 +850,26 @@ # the 'virtual_ref(frame)'). # # * if we detect that the virtual box escapes during tracing - # already (by generating a CALl_MAY_FORCE that marks the flags + # already (by generating a CALL_MAY_FORCE that marks the flags # in the vref), then we replace the vref in the list with # ConstPtr(NULL). # metainterp = self.metainterp - if metainterp.is_blackholing(): - resbox = box # good enough when blackholing - else: - vrefinfo = metainterp.staticdata.virtualref_info - obj = box.getref_base() - vref = vrefinfo.virtual_ref_during_tracing(obj) - resbox = history.BoxPtr(vref) - cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) - metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) - # Note: we allocate a JIT_VIRTUAL_REF here - # (in virtual_ref_during_tracing()), in order to detect when - # the virtual escapes during tracing already. We record it as a - # VIRTUAL_REF operation, although the backend sees this operation - # as a no-op. The point is that the backend should not really see - # it in practice, as optimizeopt.py should either kill it or - # replace it with a NEW_WITH_VTABLE followed by SETFIELD_GCs. + vrefinfo = metainterp.staticdata.virtualref_info + obj = box.getref_base() + vref = vrefinfo.virtual_ref_during_tracing(obj) + resbox = history.BoxPtr(vref) + cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) + metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) + # Note: we allocate a JIT_VIRTUAL_REF here + # (in virtual_ref_during_tracing()), in order to detect when + # the virtual escapes during tracing already. We record it as a + # VIRTUAL_REF operation. Later, optimizeopt.py should either kill + # that operation or replace it with a NEW_WITH_VTABLE followed by + # SETFIELD_GCs. metainterp.virtualref_boxes.append(box) metainterp.virtualref_boxes.append(resbox) - self.make_result_box(resbox) + return resbox @arguments("box") def opimpl_virtual_ref_finish(self, box): @@ -953,27 +879,32 @@ vrefbox = metainterp.virtualref_boxes.pop() lastbox = metainterp.virtualref_boxes.pop() assert box.getref_base() == lastbox.getref_base() - if not metainterp.is_blackholing(): - vrefinfo = metainterp.staticdata.virtualref_info - vref = vrefbox.getref_base() - if vrefinfo.is_virtual_ref(vref): - metainterp.history.record(rop.VIRTUAL_REF_FINISH, - [vrefbox, lastbox], None) + vrefinfo = metainterp.staticdata.virtualref_info + vref = vrefbox.getref_base() + if vrefinfo.is_virtual_ref(vref): + metainterp.history.record(rop.VIRTUAL_REF_FINISH, + [vrefbox, lastbox], None) # ------------------------------ def setup_call(self, argboxes): - if not we_are_translated(): - check_args(*argboxes) self.pc = 0 - self.env = argboxes + count_i = count_r = count_f = 0 + for box in argboxes: + if box.type == history.INT: + self.registers_i[count_i] = box + count_i += 1 + elif box.type == history.REF: + self.registers_r[count_r] = box + count_r += 1 + elif box.type == history.FLOAT: + self.registers_f[count_f] = box + count_f += 1 + else: + raise AssertionError(box.type) - def setup_resume_at_op(self, pc, exception_target, env): - if not we_are_translated(): - check_args(*env) + def setup_resume_at_op(self, pc): self.pc = pc - self.exception_target = exception_target - self.env = env ## values = ' '.join([box.repr_rpython() for box in self.env]) ## log('setup_resume_at_op %s:%d [%s] %d' % (self.jitcode.name, ## self.pc, values, @@ -984,25 +915,21 @@ # whenever the 'opcode_implementations' (which is one of the 'opimpl_' # methods) returns True. This is the case when the current frame # changes, due to a call or a return. - while True: - pc = self.pc - op = ord(self.bytecode[pc]) - #print self.metainterp.opcode_names[op] - self.pc = pc + 1 + try: staticdata = self.metainterp.staticdata - stop = staticdata.opcode_implementations[op](self, pc) - #self.metainterp.most_recent_mp = None - if stop: - break + while True: + pc = self.pc + op = ord(self.bytecode[pc]) + #debug_print(self.jitcode.name, pc) + #print staticdata.opcode_names[op] + staticdata.opcode_implementations[op](self, pc) + except ChangeFrame: + pass - def generate_guard(self, pc, opnum, box, extraargs=[]): + def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): if isinstance(box, Const): # no need for a guard return metainterp = self.metainterp - if metainterp.is_blackholing(): - return - saved_pc = self.pc - self.pc = pc if box is not None: moreargs = [box] + extraargs else: @@ -1020,15 +947,18 @@ virtualizable_boxes = None if metainterp.staticdata.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes + saved_pc = self.pc + if resumepc >= 0: + self.pc = resumepc resume.capture_resumedata(metainterp.framestack, virtualizable_boxes, metainterp.virtualref_boxes, resumedescr) + self.pc = saved_pc self.metainterp.staticdata.profiler.count_ops(opnum, GUARDS) # count metainterp.attach_debug_info(guard_op) - self.pc = saved_pc return guard_op - def implement_guard_value(self, pc, box): + def implement_guard_value(self, orgpc, box): """Promote the given Box into a Const. Note: be careful, it's a bit unclear what occurs if a single opcode needs to generate several ones and/or ones not near the beginning.""" @@ -1036,91 +966,138 @@ return box # no promotion needed, already a Const else: promoted_box = box.constbox() - self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box]) + self.generate_guard(rop.GUARD_VALUE, box, [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, promoted_box) return promoted_box def cls_of_box(self, box): - return self.metainterp.cpu.ts.cls_of_box(self.metainterp.cpu, box) + return self.metainterp.cpu.ts.cls_of_box(box) @specialize.arg(1) def execute(self, opnum, *argboxes): - self.execute_with_descr(opnum, None, *argboxes) + return self.metainterp.execute_and_record(opnum, None, *argboxes) @specialize.arg(1) def execute_with_descr(self, opnum, descr, *argboxes): - resbox = self.metainterp.execute_and_record(opnum, descr, *argboxes) - if resbox is not None: - self.make_result_box(resbox) + return self.metainterp.execute_and_record(opnum, descr, *argboxes) @specialize.arg(1) def execute_varargs(self, opnum, argboxes, descr, exc): + self.metainterp.clear_exception() resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes, descr=descr) - if resbox is not None: - self.make_result_box(resbox) + self.make_result_of_lastop(resbox) + # ^^^ this is done before handle_possible_exception() because we need + # the box to show up in get_list_of_active_boxes() if exc: - return self.metainterp.handle_exception() + self.metainterp.handle_possible_exception() else: - return self.metainterp.assert_no_exception() + self.metainterp.assert_no_exception() + return resbox - def do_residual_call(self, argboxes, descr, exc): + def do_residual_call(self, funcbox, descr, argboxes, + assembler_call_token=None): + # First build allboxes: it may need some reordering from the + # list provided in argboxes, depending on the order in which + # the arguments are expected by the function + allboxes = [None] * (len(argboxes)+1) + allboxes[0] = funcbox + src_i = src_r = src_f = 0 + i = 1 + for kind in descr.get_arg_types(): + if kind == history.INT: + while True: + box = argboxes[src_i] + src_i += 1 + if box.type == history.INT: + break + elif kind == history.REF: + while True: + box = argboxes[src_r] + src_r += 1 + if box.type == history.REF: + break + elif kind == history.FLOAT: + while True: + box = argboxes[src_f] + src_f += 1 + if box.type == history.FLOAT: + break + else: + raise AssertionError + allboxes[i] = box + i += 1 + assert i == len(allboxes) + # effectinfo = descr.get_extra_info() - if effectinfo is None or effectinfo.forces_virtual_or_virtualizable: + if (effectinfo is None or + effectinfo.extraeffect == + effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE or + assembler_call_token is not None): # residual calls require attention to keep virtualizables in-sync + self.metainterp.clear_exception() self.metainterp.vable_and_vrefs_before_residual_call() - # xxx do something about code duplication resbox = self.metainterp.execute_and_record_varargs( - rop.CALL_MAY_FORCE, argboxes, descr=descr) - self.metainterp.vable_and_vrefs_after_residual_call() + rop.CALL_MAY_FORCE, allboxes, descr=descr) + self.metainterp.vrefs_after_residual_call() + if assembler_call_token is not None: + self.metainterp.direct_assembler_call(assembler_call_token) if resbox is not None: - self.make_result_box(resbox) - self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, []) - if exc: - return self.metainterp.handle_exception() + self.make_result_of_lastop(resbox) + self.metainterp.vable_after_residual_call() + self.generate_guard(rop.GUARD_NOT_FORCED, None) + self.metainterp.handle_possible_exception() + return resbox + else: + effect = effectinfo.extraeffect + if effect == effectinfo.EF_CANNOT_RAISE: + return self.execute_varargs(rop.CALL, allboxes, descr, False) + elif effect == effectinfo.EF_PURE: + return self.execute_varargs(rop.CALL_PURE, allboxes, + descr, False) + elif effect == effectinfo.EF_LOOPINVARIANT: + return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes, + descr, True) else: - return self.metainterp.assert_no_exception() + return self.execute_varargs(rop.CALL, allboxes, descr, True) + + def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes): + """The 'residual_call' operation is emitted in two cases: + when we have to generate a residual CALL operation, but also + to handle an indirect_call that may need to be inlined.""" + assert isinstance(funcbox, Const) + sd = self.metainterp.staticdata + key = sd.cpu.ts.getaddr_for_box(funcbox) + jitcode = sd.bytecode_for_address(key) + if jitcode is not None: + # we should follow calls to this graph + return self.metainterp.perform_call(jitcode, argboxes) else: - return self.execute_varargs(rop.CALL, argboxes, descr, exc) + # but we should not follow calls to that graph + return self.do_residual_call(funcbox, calldescr, argboxes) # ____________________________________________________________ class MetaInterpStaticData(object): - virtualizable_info = None logger_noopt = None logger_ops = None - def __init__(self, portal_graph, cpu, stats, options, + def __init__(self, cpu, options, ProfilerClass=EmptyProfiler, warmrunnerdesc=None): self.cpu = cpu - self.stats = stats + self.stats = self.cpu.stats self.options = options self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) - RESULT = portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) - - self.opcode_implementations = [] - self.opcode_names = [] - self.opname_to_index = {} - self.profiler = ProfilerClass() - - self.indirectcall_keys = [] - self.indirectcall_values = [] - self.warmrunnerdesc = warmrunnerdesc - self._op_goto_if_not = self.find_opcode('goto_if_not') - self._op_ooisnull = self.find_opcode('ooisnull') - self._op_oononnull = self.find_opcode('oononnull') backendmodule = self.cpu.__module__ backendmodule = backendmodule.split('.')[-2] self.jit_starting_line = 'JIT starting (%s)' % backendmodule - self.portal_code = None - self._class_sizes = None self._addr2name_keys = [] self._addr2name_values = [] @@ -1132,15 +1109,44 @@ def _freeze_(self): return True - def info_from_codewriter(self, portal_code, class_sizes, - list_of_addr2name, portal_runner_ptr): - self.portal_code = portal_code - self._class_sizes = class_sizes - self._addr2name_keys = [key for key, value in list_of_addr2name] + def setup_insns(self, insns): + self.opcode_names = ['?'] * len(insns) + self.opcode_implementations = [None] * len(insns) + for key, value in insns.items(): + assert self.opcode_implementations[value] is None + self.opcode_names[value] = key + name, argcodes = key.split('/') + opimpl = _get_opimpl_method(name, argcodes) + self.opcode_implementations[value] = opimpl + self.op_catch_exception = insns.get('catch_exception/L', -1) + + def setup_descrs(self, descrs): + self.opcode_descrs = descrs + + def setup_indirectcalltargets(self, indirectcalltargets): + self.indirectcalltargets = list(indirectcalltargets) + + def setup_list_of_addr2name(self, list_of_addr2name): + self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] - self._portal_runner_ptr = portal_runner_ptr - def finish_setup(self, optimizer=None): + def finish_setup(self, codewriter, optimizer=None): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) + # + asm = codewriter.assembler + self.setup_insns(asm.insns) + self.setup_descrs(asm.descrs) + self.setup_indirectcalltargets(asm.indirectcalltargets) + self.setup_list_of_addr2name(asm.list_of_addr2name) + # + self.portal_code = codewriter.mainjitcode + self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.virtualref_info = codewriter.callcontrol.virtualref_info + self.virtualizable_info = codewriter.callcontrol.virtualizable_info + RESULT = codewriter.portal_graph.getreturnvar().concretetype + self.result_type = history.getkind(RESULT) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args @@ -1156,20 +1162,12 @@ """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: debug_print(self.jit_starting_line) - self._setup_class_sizes() self.cpu.setup_once() if not self.profiler.initialized: self.profiler.start() self.profiler.initialized = True self.globaldata.initialized = True - def _setup_class_sizes(self): - class_sizes = {} - for vtable, sizedescr in self._class_sizes: - vtable = self.cpu.ts.cast_vtable_to_hashable(self.cpu, vtable) - class_sizes[vtable] = sizedescr - self.cpu.set_class_sizes(class_sizes) - def get_name_from_address(self, addr): # for debugging only if we_are_translated(): @@ -1200,39 +1198,16 @@ # because the keys are function addresses, so they # can change from run to run. d = {} - keys = self.indirectcall_keys - values = self.indirectcall_values - for i in range(len(keys)): - d[keys[i]] = values[i] + for jitcode in self.indirectcalltargets: + d[jitcode.fnaddr] = jitcode self.globaldata.indirectcall_dict = d return d.get(fnaddress, None) else: - for i in range(len(self.indirectcall_keys)): - if fnaddress == self.indirectcall_keys[i]: - return self.indirectcall_values[i] + for jitcode in self.indirectcalltargets: + if jitcode.fnaddr == fnaddress: + return jitcode return None - # ---------- construction-time interface ---------- - - def _register_indirect_call_target(self, fnaddress, jitcode): - self.indirectcall_keys.append(fnaddress) - self.indirectcall_values.append(jitcode) - - def find_opcode(self, name): - try: - return self.opname_to_index[name] - except KeyError: - self._register_opcode(name) - return self.opname_to_index[name] - - def _register_opcode(self, opname): - assert len(self.opcode_implementations) < 256, \ - "too many implementations of opcodes!" - name = "opimpl_" + opname - self.opname_to_index[opname] = len(self.opcode_implementations) - self.opcode_names.append(opname) - self.opcode_implementations.append(getattr(MIFrame, name).im_func) - # ---------------- logging ------------------------ def log(self, msg): @@ -1259,6 +1234,7 @@ self.addr2name = None self.loopnumbering = 0 self.resume_virtuals = {} + self.resume_virtuals_not_translated = [] # state = staticdata.state if state is not None: @@ -1283,23 +1259,32 @@ class MetaInterp(object): in_recursion = 0 - _already_allocated_resume_virtuals = None def __init__(self, staticdata): self.staticdata = staticdata self.cpu = staticdata.cpu self.portal_trace_positions = [] + self.free_frames_list = [] + self.last_exc_value_box = None - def is_blackholing(self): - return self.history is None + def perform_call(self, jitcode, boxes, greenkey=None): + # causes the metainterp to enter the given subfunction + # with a special case for recursive portal calls + f = self.newframe(jitcode, greenkey) + f.setup_call(boxes) + raise ChangeFrame def newframe(self, jitcode, greenkey=None): if jitcode is self.staticdata.portal_code: self.in_recursion += 1 - if greenkey is not None and not self.is_blackholing(): + if greenkey is not None: self.portal_trace_positions.append( (greenkey, len(self.history.operations))) - f = MIFrame(self, jitcode, greenkey) + if len(self.free_frames_list) > 0: + f = self.free_frames_list.pop() + else: + f = MIFrame(self) + f.setup(jitcode, greenkey) self.framestack.append(f) return f @@ -1307,23 +1292,27 @@ frame = self.framestack.pop() if frame.jitcode is self.staticdata.portal_code: self.in_recursion -= 1 - if frame.greenkey is not None and not self.is_blackholing(): + if frame.greenkey is not None: self.portal_trace_positions.append( (None, len(self.history.operations))) - return frame + # we save the freed MIFrames to avoid needing to re-create new + # MIFrame objects all the time; they are a bit big, with their + # 3*256 register entries. + frame.cleanup_registers() + self.free_frames_list.append(frame) def finishframe(self, resultbox): - frame = self.popframe() + # handle a non-exceptional return from the current frame + self.last_exc_value_box = None + self.popframe() if self.framestack: - if resultbox is not None: - self.framestack[-1].make_result_box(resultbox) - return True + self.framestack[-1].make_result_of_lastop(resultbox) + raise ChangeFrame else: - if not self.is_blackholing(): - try: - self.compile_done_with_this_frame(resultbox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_done_with_this_frame(resultbox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) sd = self.staticdata if sd.result_type == 'void': assert resultbox is None @@ -1337,30 +1326,25 @@ else: assert False - def finishframe_exception(self, exceptionbox, excvaluebox): - # detect and propagate some exceptions early: - # - AssertionError - # - all subclasses of JitException - if we_are_translated(): - from pypy.jit.metainterp.warmspot import JitException - e = self.cpu.ts.get_exception_obj(excvaluebox) - if isinstance(e, JitException) or isinstance(e, AssertionError): - raise Exception, e - # + def finishframe_exception(self): + excvaluebox = self.last_exc_value_box while self.framestack: frame = self.framestack[-1] - if frame.exception_target >= 0: - frame.pc = frame.exception_target - frame.exception_target = -1 - frame.exception_box = exceptionbox - frame.exc_value_box = excvaluebox - return True + code = frame.bytecode + position = frame.pc # <-- just after the insn that raised + if position < len(code): + opcode = ord(code[position]) + if opcode == self.staticdata.op_catch_exception: + # found a 'catch_exception' instruction; + # jump to the handler + target = ord(code[position+1]) | (ord(code[position+2])<<8) + frame.pc = target + raise ChangeFrame self.popframe() - if not self.is_blackholing(): - try: - self.compile_exit_frame_with_exception(excvaluebox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_exit_frame_with_exception(excvaluebox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base()) def check_recursion_invariant(self): @@ -1379,19 +1363,7 @@ else: print " ", print jitcode.name - raise Exception - - def raise_overflow_error(self): - etype, evalue = self.cpu.get_overflow_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) - - def raise_zero_division_error(self): - etype, evalue = self.cpu.get_zero_division_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) + raise AssertionError def create_empty_history(self): warmrunnerstate = self.staticdata.state @@ -1412,15 +1384,11 @@ @specialize.arg(1) def execute_and_record(self, opnum, descr, *argboxes): history.check_descr(descr) - assert (opnum != rop.CALL and opnum != rop.CALL_MAY_FORCE - and opnum != rop.OOSEND) + assert not (rop._CANRAISE_FIRST <= opnum <= rop._CANRAISE_LAST) # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - return resbox + resbox = executor.execute(self.cpu, self, opnum, descr, *argboxes) if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: return self._record_helper_pure(opnum, resbox, descr, *argboxes) else: @@ -1433,16 +1401,14 @@ # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute_varargs(self.cpu, opnum, argboxes, descr) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - else: - # check if the operation can be constant-folded away - argboxes = list(argboxes) - if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: - resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) - else: - resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) + resbox = executor.execute_varargs(self.cpu, self, + opnum, argboxes, descr) + # check if the operation can be constant-folded away + argboxes = list(argboxes) + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: + resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) + else: + resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) return resbox def _record_helper_pure(self, opnum, resbox, descr, *argboxes): @@ -1478,45 +1444,57 @@ op.pc = self.framestack[-1].pc op.name = self.framestack[-1].jitcode.name - def switch_to_blackhole(self, reason): + def execute_raised(self, exception, constant=False): + if isinstance(exception, JitException): + raise JitException, exception # go through + llexception = get_llexception(self.cpu, exception) + self.execute_ll_raised(llexception, constant) + + def execute_ll_raised(self, llexception, constant=False): + # Exception handling: when execute.do_call() gets an exception it + # calls metainterp.execute_raised(), which puts it into + # 'self.last_exc_value_box'. This is used shortly afterwards + # to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also + # to handle the following opcodes 'goto_if_exception_mismatch'. + llexception = self.cpu.ts.cast_to_ref(llexception) + exc_value_box = self.cpu.ts.get_exc_value_box(llexception) + if constant: + exc_value_box = exc_value_box.constbox() + self.last_exc_value_box = exc_value_box + self.class_of_last_exc_is_const = constant + # 'class_of_last_exc_is_const' means that the class of the value + # stored in the exc_value Box can be assumed to be a Const. This + # is only True after a GUARD_EXCEPTION or GUARD_CLASS. + + def clear_exception(self): + self.last_exc_value_box = None + + def aborted_tracing(self, reason): self.staticdata.profiler.count(reason) debug_print('~~~ ABORTING TRACING') - debug_stop('jit-tracing') - debug_start('jit-blackhole') - self.history = None # start blackholing self.staticdata.stats.aborted() - self.staticdata.profiler.end_tracing() - self.staticdata.profiler.start_blackhole() self.resumekey.reset_counter_from_failure() - switch_to_blackhole._dont_inline_ = True - def switch_to_blackhole_if_trace_too_long(self): - if not self.is_blackholing(): - warmrunnerstate = self.staticdata.state - if len(self.history.operations) > warmrunnerstate.trace_limit: - greenkey_of_huge_function = self.find_biggest_function() - self.portal_trace_positions = None - self.switch_to_blackhole(ABORT_TOO_LONG) - if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state - warmrunnerstate.disable_noninlinable_function( - greenkey_of_huge_function) + def blackhole_if_trace_too_long(self): + warmrunnerstate = self.staticdata.state + if len(self.history.operations) > warmrunnerstate.trace_limit: + greenkey_of_huge_function = self.find_biggest_function() + self.portal_trace_positions = None + if greenkey_of_huge_function is not None: + warmrunnerstate = self.staticdata.state + warmrunnerstate.disable_noninlinable_function( + greenkey_of_huge_function) + raise SwitchToBlackhole(ABORT_TOO_LONG) def _interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, - # a ContinueRunningNormally, or a GenerateMergePoint exception. + # a ExitFrameWithException, or a GenerateMergePoint exception. self.staticdata.stats.entered() - try: - while True: - self.framestack[-1].run_one_step() - self.switch_to_blackhole_if_trace_too_long() - if not we_are_translated(): - self.check_recursion_invariant() - finally: - if self.is_blackholing(): - self.staticdata.profiler.end_blackhole() - else: - self.staticdata.profiler.end_tracing() + while True: + self.framestack[-1].run_one_step() + self.blackhole_if_trace_too_long() + if not we_are_translated(): + self.check_recursion_invariant() def interpret(self): if we_are_translated(): @@ -1527,20 +1505,19 @@ except: import sys if sys.exc_info()[0] is not None: - codewriter.log.info(sys.exc_info()[0].__name__) + self.staticdata.log(sys.exc_info()[0].__name__) raise def compile_and_run_once(self, *args): debug_start('jit-tracing') self.staticdata._setup_once() + self.staticdata.profiler.start_tracing() self.create_empty_history() try: return self._compile_and_run_once(*args) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _compile_and_run_once(self, *args): original_boxes = self.initialize_state_from_start(*args) @@ -1553,20 +1530,22 @@ self.seen_can_enter_jit = False try: self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" def handle_guard_failure(self, key): + debug_start('jit-tracing') + self.staticdata.profiler.start_tracing() assert isinstance(key, compile.ResumeGuardDescr) self.initialize_state_from_guard_failure(key) try: return self._handle_guard_failure(key) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _handle_guard_failure(self, key): original_greenkey = key.original_greenkey @@ -1579,13 +1558,23 @@ try: self.prepare_resume_from_failure(key.guard_opnum) self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" + + def run_blackhole_interp_to_cancel_tracing(self, stb): + # We got a SwitchToBlackhole exception. Convert the framestack into + # a stack of blackhole interpreters filled with the same values, and + # run it. + from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl + self.aborted_tracing(stb.reason) + convert_and_run_from_pyjitpl(self, stb.raising_exception) + assert False # ^^^ must raise - def remove_consts_and_duplicates(self, boxes, startindex, endindex, - duplicates): - for i in range(startindex, endindex): + def remove_consts_and_duplicates(self, boxes, endindex, duplicates): + for i in range(endindex): box = boxes[i] if isinstance(box, Const) or box in duplicates: oldbox = box @@ -1595,22 +1584,19 @@ else: duplicates[box] = None - def reached_can_enter_jit(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + def reached_can_enter_jit(self, greenboxes, redboxes): duplicates = {} - self.remove_consts_and_duplicates(live_arg_boxes, - num_green_args, - len(live_arg_boxes), + self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) - live_arg_boxes = live_arg_boxes[:] + live_arg_boxes = greenboxes + redboxes if self.staticdata.virtualizable_info is not None: - # we use ':-1' to remove the last item, which is the virtualizable + # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, - 0, len(self.virtualizable_boxes)-1, duplicates) - live_arg_boxes += self.virtualizable_boxes[:-1] + live_arg_boxes += self.virtualizable_boxes + live_arg_boxes.pop() assert len(self.virtualref_boxes) == 0, "missing virtual_ref_finish()?" # Called whenever we reach the 'can_enter_jit' hint. # First, attempt to make a bridge: @@ -1639,11 +1625,12 @@ # Found! Compile it as a loop. if start < 0: # we cannot reconstruct the beginning of the proper loop - raise GiveUp + raise SwitchToBlackhole(ABORT_BRIDGE) # raises in case it works -- which is the common case self.compile(original_boxes, live_arg_boxes, start) # creation of the loop was cancelled! + self.staticdata.log('cancelled, going on...') # Otherwise, no loop found so far, so continue tracing. start = len(self.history.operations) @@ -1658,17 +1645,39 @@ return loop_token def prepare_resume_from_failure(self, opnum): + frame = self.framestack[-1] if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now - self.framestack[-1].follow_jump() + frame.pc = frame.jitcode.follow_jump(frame.pc) elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping - self.framestack[-1].dont_follow_jump() - elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION - or opnum == rop.GUARD_NOT_FORCED): - self.handle_exception() + pass + elif opnum == rop.GUARD_VALUE or opnum == rop.GUARD_CLASS: + pass # the pc is already set to the *start* of the opcode + elif (opnum == rop.GUARD_NONNULL or + opnum == rop.GUARD_ISNULL or + opnum == rop.GUARD_NONNULL_CLASS): + pass # the pc is already set to the *start* of the opcode + elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION: + exception = self.cpu.grab_exc_value() + if exception: + self.execute_ll_raised(lltype.cast_opaque_ptr(rclass.OBJECTPTR, + exception)) + else: + self.clear_exception() + try: + self.handle_possible_exception() + except ChangeFrame: + pass elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected - self.raise_overflow_error() - elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL: - self.framestack[-1].ignore_next_guard_nullness(opnum) + self.execute_raised(OverflowError(), constant=True) + try: + self.finishframe_exception() + except ChangeFrame: + pass + elif opnum == rop.GUARD_OVERFLOW: # no longer overflowing + self.clear_exception() + else: + from pypy.jit.metainterp.resoperation import opname + raise NotImplementedError(opname[opnum]) def compile(self, original_boxes, live_arg_boxes, start): num_green_args = self.staticdata.num_green_args @@ -1720,7 +1729,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1731,7 +1740,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests @@ -1753,15 +1762,13 @@ def initialize_state_from_start(self, *args): self.in_recursion = -1 # always one portal around - self.staticdata.profiler.start_tracing() num_green_args = self.staticdata.num_green_args original_boxes = [] self._initialize_from_start(original_boxes, num_green_args, *args) # ----- make a new frame ----- self.framestack = [] f = self.newframe(self.staticdata.portal_code) - f.pc = 0 - f.env = original_boxes[:] + f.setup_call(original_boxes) self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) return original_boxes @@ -1769,20 +1776,9 @@ def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack self.in_recursion = -1 # always one portal around - inputargs_and_holes = self.cpu.make_boxes_from_latest_values( - resumedescr) - must_compile = resumedescr.must_compile(self.staticdata, - inputargs_and_holes) - if must_compile: - debug_start('jit-tracing') - self.history = history.History() - self.history.inputargs = [box for box in inputargs_and_holes if box] - self.staticdata.profiler.start_tracing() - else: - debug_start('jit-blackhole') - self.staticdata.profiler.start_blackhole() - self.history = None # this means that is_blackholing() is true - self.rebuild_state_after_failure(resumedescr, inputargs_and_holes) + self.history = history.History() + inputargs_and_holes = self.rebuild_state_after_failure(resumedescr) + self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): vinfo = self.staticdata.virtualizable_info @@ -1804,9 +1800,6 @@ vinfo.clear_vable_token(virtualizable) def vable_and_vrefs_before_residual_call(self): - if self.is_blackholing(): - return - # vrefinfo = self.staticdata.virtualref_info for i in range(1, len(self.virtualref_boxes), 2): vrefbox = self.virtualref_boxes[i] @@ -1827,37 +1820,31 @@ force_token_box], None, descr=vinfo.vable_token_descr) - def vable_and_vrefs_after_residual_call(self): - if self.is_blackholing(): - escapes = True - else: - escapes = False - # - vrefinfo = self.staticdata.virtualref_info - for i in range(0, len(self.virtualref_boxes), 2): - virtualbox = self.virtualref_boxes[i] - vrefbox = self.virtualref_boxes[i+1] - vref = vrefbox.getref_base() - if vrefinfo.tracing_after_residual_call(vref): - # this vref was really a virtual_ref, but it escaped - # during this CALL_MAY_FORCE. Mark this fact by - # generating a VIRTUAL_REF_FINISH on it and replacing - # it by ConstPtr(NULL). - self.stop_tracking_virtualref(i) - # - vinfo = self.staticdata.virtualizable_info - if vinfo is not None: - virtualizable_box = self.virtualizable_boxes[-1] - virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) - if vinfo.tracing_after_residual_call(virtualizable): - # the virtualizable escaped during CALL_MAY_FORCE. - escapes = True - # - if escapes: - self.switch_to_blackhole(ABORT_ESCAPE) - # - if escapes: - self.load_fields_from_virtualizable() + def vrefs_after_residual_call(self): + vrefinfo = self.staticdata.virtualref_info + for i in range(0, len(self.virtualref_boxes), 2): + virtualbox = self.virtualref_boxes[i] + vrefbox = self.virtualref_boxes[i+1] + vref = vrefbox.getref_base() + if vrefinfo.tracing_after_residual_call(vref): + # this vref was really a virtual_ref, but it escaped + # during this CALL_MAY_FORCE. Mark this fact by + # generating a VIRTUAL_REF_FINISH on it and replacing + # it by ConstPtr(NULL). + self.stop_tracking_virtualref(i) + + def vable_after_residual_call(self): + vinfo = self.staticdata.virtualizable_info + if vinfo is not None: + virtualizable_box = self.virtualizable_boxes[-1] + virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + if vinfo.tracing_after_residual_call(virtualizable): + # the virtualizable escaped during CALL_MAY_FORCE. + self.load_fields_from_virtualizable() + raise SwitchToBlackhole(ABORT_ESCAPE, raising_exception=True) + # ^^^ we set 'raising_exception' to True because we must still + # have the eventual exception raised (this is normally done + # after the call to vable_after_residual_call()). def stop_tracking_virtualref(self, i): virtualbox = self.virtualref_boxes[i] @@ -1871,44 +1858,37 @@ # mark by replacing it with ConstPtr(NULL) self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL - def handle_exception(self): - etype = self.cpu.get_exception() - evalue = self.cpu.get_exc_value() - assert bool(etype) == bool(evalue) - self.cpu.clear_exception() + def handle_possible_exception(self): frame = self.framestack[-1] - if etype: - exception_box = self.cpu.ts.get_exception_box(etype) - exc_value_box = self.cpu.ts.get_exc_value_box(evalue) - op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION, + if self.last_exc_value_box is not None: + exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box) + op = frame.generate_guard(rop.GUARD_EXCEPTION, None, [exception_box]) - if op: - op.result = exc_value_box - return self.finishframe_exception(exception_box, exc_value_box) + assert op is not None + op.result = self.last_exc_value_box + self.class_of_last_exc_is_const = True + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) - return False - - def assert_no_exception(self): - assert not self.cpu.get_exception() - return False + frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) - def handle_overflow_error(self): + def handle_possible_overflow_error(self): frame = self.framestack[-1] - if self.cpu._overflow_flag: - self.cpu._overflow_flag = False - frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None, []) - return self.raise_overflow_error() + if self.last_exc_value_box is not None: + frame.generate_guard(rop.GUARD_OVERFLOW, None) + assert isinstance(self.last_exc_value_box, Const) + assert self.class_of_last_exc_is_const + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None, []) - return False + frame.generate_guard(rop.GUARD_NO_OVERFLOW, None) + + def assert_no_exception(self): + assert self.last_exc_value_box is None - def rebuild_state_after_failure(self, resumedescr, newboxes): + def rebuild_state_after_failure(self, resumedescr): vinfo = self.staticdata.virtualizable_info self.framestack = [] - expect_virtualizable = vinfo is not None - virtualizable_boxes, virtualref_boxes = resume.rebuild_from_resumedata( - self, newboxes, resumedescr, expect_virtualizable) + boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) + inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists # # virtual refs: make the vrefs point to the freshly allocated virtuals self.virtualref_boxes = virtualref_boxes @@ -1921,7 +1901,7 @@ # # virtualizable: synchronize the real virtualizable and the local # boxes, in whichever direction is appropriate - if expect_virtualizable: + if vinfo is not None: self.virtualizable_boxes = virtualizable_boxes # just jumped away from assembler (case 4 in the comment in # virtualizable.py) into tracing (case 2); check that vable_token @@ -1930,13 +1910,14 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if self._already_allocated_resume_virtuals is not None: + if 0: ## self._already_allocated_resume_virtuals is not None: # resuming from a ResumeGuardForcedDescr: load the new values # currently stored on the virtualizable fields self.load_fields_from_virtualizable() else: # normal case: fill the virtualizable with the local boxes self.synchronize_virtualizable() + return inputargs_and_holes def check_synchronized_virtualizable(self): if not we_are_translated(): @@ -1953,8 +1934,8 @@ def load_fields_from_virtualizable(self): # Force a reload of the virtualizable fields into the local - # boxes (called only in escaping cases) - assert self.is_blackholing() + # boxes (called only in escaping cases). Only call this function + # just before SwitchToBlackhole. vinfo = self.staticdata.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] @@ -2003,11 +1984,9 @@ return boxes def replace_box(self, oldbox, newbox): + assert isinstance(oldbox, Box) for frame in self.framestack: - boxes = frame.env - for i in range(len(boxes)): - if boxes[i] is oldbox: - boxes[i] = newbox + frame.replace_active_box_in_frame(oldbox, newbox) boxes = self.virtualref_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2019,8 +1998,6 @@ boxes[i] = newbox def find_biggest_function(self): - assert not self.is_blackholing() - start_stack = [] max_size = 0 max_key = None @@ -2042,23 +2019,158 @@ max_key = key return max_key - def direct_assembler_call(self, pc, varargs, token, call_position): - """ Generate a direct call to assembler for portal entry point. + def direct_assembler_call(self, token): + """ Generate a direct call to assembler for portal entry point, + patching the CALL_MAY_FORCE that occurred just now. """ - assert not self.is_blackholing() # XXX + op = self.history.operations.pop() + assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args - args = varargs[num_green_args + 1:] - resbox = self.history.operations[call_position].result - rest = self.history.slice_history_at(call_position) + args = op.args[num_green_args + 1:] if self.staticdata.virtualizable_info is not None: vindex = self.staticdata.virtualizable_info.index_of_virtualizable vbox = args[vindex - num_green_args] - args += self.gen_load_from_other_virtualizable(vbox) - self.history.record(rop.CALL_ASSEMBLER, args[:], resbox, descr=token) - self.history.operations += rest + args = args + self.gen_load_from_other_virtualizable(vbox) + # ^^^ and not "+=", which makes 'args' a resizable list + op.opnum = rop.CALL_ASSEMBLER + op.args = args + op.descr = token + self.history.operations.append(op) -class GenerateMergePoint(Exception): +# ____________________________________________________________ + +class GenerateMergePoint(JitException): def __init__(self, args, target_loop_token): assert target_loop_token is not None self.argboxes = args self.target_loop_token = target_loop_token + +class ChangeFrame(JitException): + """Raised after we mutated metainterp.framestack, in order to force + it to reload the current top-of-stack frame that gets interpreted.""" + +class SwitchToBlackhole(JitException): + def __init__(self, reason, raising_exception=False): + self.reason = reason + self.raising_exception = raising_exception + # ^^^ must be set to True if the SwitchToBlackhole is raised at a + # point where the exception on metainterp.last_exc_value_box + # is supposed to be raised. The default False means that it + # should just be copied into the blackhole interp, but not raised. + +# ____________________________________________________________ + +def _get_opimpl_method(name, argcodes): + from pypy.jit.metainterp.blackhole import signedord + # + def handler(self, position): + assert position >= 0 + args = () + next_argcode = 0 + code = self.bytecode + orgpc = position + position += 1 + for argtype in argtypes: + if argtype == "box": # a box, of whatever type + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = self.registers_i[ord(code[position])] + elif argcode == 'c': + value = ConstInt(signedord(code[position])) + elif argcode == 'r': + value = self.registers_r[ord(code[position])] + elif argcode == 'f': + value = self.registers_f[ord(code[position])] + else: + raise AssertionError("bad argcode") + position += 1 + elif argtype == "descr" or argtype == "jitcode": + assert argcodes[next_argcode] == 'd' + next_argcode = next_argcode + 1 + index = ord(code[position]) | (ord(code[position+1])<<8) + value = self.metainterp.staticdata.opcode_descrs[index] + if argtype == "jitcode": + assert isinstance(value, JitCode) + position += 2 + elif argtype == "label": + assert argcodes[next_argcode] == 'L' + next_argcode = next_argcode + 1 + value = ord(code[position]) | (ord(code[position+1])<<8) + position += 2 + elif argtype == "boxes": # a list of boxes of some type + length = ord(code[position]) + value = [None] * length + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + next_argcode = next_argcode + 1 + position += 1 + length + elif argtype == "boxes2": # two lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + value = [None] * (length1 + length2) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + next_argcode = next_argcode + 2 + position = position2 + 1 + length2 + elif argtype == "boxes3": # three lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + position3 = position2 + 1 + length2 + length3 = ord(code[position3]) + value = [None] * (length1 + length2 + length3) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + self.prepare_list_of_boxes(value, length1 + length2, position3, + argcodes[next_argcode + 2]) + next_argcode = next_argcode + 3 + position = position3 + 1 + length3 + elif argtype == "orgpc": + value = orgpc + else: + raise AssertionError("bad argtype: %r" % (argtype,)) + args += (value,) + # + num_return_args = len(argcodes) - next_argcode + assert num_return_args == 0 or num_return_args == 2 + if num_return_args: + # Save the type of the resulting box. This is needed if there is + # a get_list_of_active_boxes(). See comments there. + self._result_argcode = argcodes[next_argcode + 1] + position += 1 + else: + self._result_argcode = 'v' + self.pc = position + # + if not we_are_translated(): + print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))), + try: + resultbox = unboundmethod(self, *args) + except Exception, e: + print '-> %s!' % e.__class__.__name__ + raise + if num_return_args == 0: + print + assert resultbox is None + else: + print '-> %r' % (resultbox,) + assert argcodes[next_argcode] == '>' + result_argcode = argcodes[next_argcode + 1] + assert resultbox.type == {'i': history.INT, + 'r': history.REF, + 'f': history.FLOAT}[result_argcode] + else: + resultbox = unboundmethod(self, *args) + # + self.make_result_of_lastop(resultbox) + # + unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func + argtypes = unrolling_iterable(unboundmethod.argtypes) + handler.func_name = 'handler_' + name + return handler Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resoperation.py (original) +++ pypy/trunk/pypy/jit/metainterp/resoperation.py Tue Jun 8 23:42:50 2010 @@ -22,10 +22,11 @@ self.setdescr(descr) def setdescr(self, descr): - # for 'call', 'new', 'getfield_gc'...: the descr is a number provided - # by the backend holding details about the type of the operation -- - # actually an instance of a class, typically Descr, that inherits - # from AbstractDescr + # for 'call', 'new', 'getfield_gc'...: the descr is a prebuilt + # instance provided by the backend holding details about the type + # of the operation. It must inherit from AbstractDescr. The + # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(), + # cpu.calldescrof(), and cpu.typedescrof(). from pypy.jit.metainterp.history import check_descr check_descr(descr) self.descr = descr @@ -134,10 +135,9 @@ '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations ----- '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations ----- - 'OOSEND_PURE', # ootype operation + #'OOSEND_PURE', # ootype operation 'CALL_PURE', # - 'CAST_PTR_TO_INT/1', 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', @@ -156,7 +156,6 @@ 'FLOAT_TRUEDIV/2', 'FLOAT_NEG/1', 'FLOAT_ABS/1', - 'FLOAT_IS_TRUE/1b', 'CAST_FLOAT_TO_INT/1', 'CAST_INT_TO_FLOAT/1', # @@ -177,15 +176,15 @@ 'FLOAT_GT/2b', 'FLOAT_GE/2b', # + 'INT_IS_ZERO/1b', 'INT_IS_TRUE/1b', 'INT_NEG/1', 'INT_INVERT/1', - 'BOOL_NOT/1b', # 'SAME_AS/1', # gets a Const or a Box, turns it into another Box # - 'OOIS/2b', - 'OOISNOT/2b', + 'PTR_EQ/2b', + 'PTR_NE/2b', # 'ARRAYLEN_GC/1d', 'STRLEN/1', @@ -197,8 +196,8 @@ 'UNICODEGETITEM/2', # # ootype operations - 'INSTANCEOF/1db', - 'SUBCLASSOF/2b', + #'INSTANCEOF/1db', + #'SUBCLASSOF/2b', # '_ALWAYS_PURE_LAST', # ----- end of always_pure operations ----- @@ -209,29 +208,29 @@ 'NEW_WITH_VTABLE/1', 'NEW_ARRAY/1d', 'FORCE_TOKEN/0', - 'VIRTUAL_REF/2', + 'VIRTUAL_REF/2', # removed before it's passed to the backend '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations ----- 'SETARRAYITEM_GC/3d', 'SETARRAYITEM_RAW/3d',#only added by backend.llsupport.gc.rewrite_assembler 'SETFIELD_GC/2d', 'SETFIELD_RAW/2d', - 'ARRAYCOPY/7d', + 'ARRAYCOPY/7d', # removed before it's passed to the backend 'NEWSTR/1', 'STRSETITEM/3', 'UNICODESETITEM/3', 'NEWUNICODE/1', - 'RUNTIMENEW/1', # ootype operation + #'RUNTIMENEW/1', # ootype operation 'COND_CALL_GC_WB', # [objptr, newvalue] (for the write barrier) 'DEBUG_MERGE_POINT/1', # debugging only - 'VIRTUAL_REF_FINISH/2', + 'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend '_CANRAISE_FIRST', # ----- start of can_raise operations ----- 'CALL', 'CALL_ASSEMBLER', 'CALL_MAY_FORCE', 'CALL_LOOPINVARIANT', - 'OOSEND', # ootype operation + #'OOSEND', # ootype operation '_CANRAISE_LAST', # ----- end of can_raise operations ----- '_OVF_FIRST', # ----- start of is_ovf operations ----- Modified: pypy/trunk/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resume.py (original) +++ pypy/trunk/pypy/jit/metainterp/resume.py Tue Jun 8 23:42:50 2010 @@ -1,10 +1,12 @@ import sys, os -from pypy.jit.metainterp.history import Box, Const, ConstInt, INT, REF +from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat +from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import jitprof -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rlib import rarithmetic -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print @@ -21,26 +23,29 @@ self.boxes = boxes class FrameInfo(object): - __slots__ = ('prev', 'jitcode', 'pc', 'exception_target') + __slots__ = ('prev', 'jitcode', 'pc') - def __init__(self, prev, frame): + def __init__(self, prev, jitcode, pc): self.prev = prev - self.jitcode = frame.jitcode - self.pc = frame.pc - self.exception_target = frame.exception_target + self.jitcode = jitcode + self.pc = pc def _ensure_parent_resumedata(framestack, n): target = framestack[n] - if n == 0 or target.parent_resumedata_frame_info_list is not None: + if n == 0: return - _ensure_parent_resumedata(framestack, n-1) back = framestack[n-1] + if target.parent_resumedata_frame_info_list is not None: + assert target.parent_resumedata_frame_info_list.pc == back.pc + return + _ensure_parent_resumedata(framestack, n-1) target.parent_resumedata_frame_info_list = FrameInfo( back.parent_resumedata_frame_info_list, - back) + back.jitcode, + back.pc) target.parent_resumedata_snapshot = Snapshot( back.parent_resumedata_snapshot, - back.env[:]) + back.get_list_of_active_boxes(True)) def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, storage): @@ -48,12 +53,15 @@ top = framestack[n] _ensure_parent_resumedata(framestack, n) frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, - top) + top.jitcode, top.pc) storage.rd_frame_info_list = frame_info_list - snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:]) - snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now + snapshot = Snapshot(top.parent_resumedata_snapshot, + top.get_list_of_active_boxes(False)) if virtualizable_boxes is not None: - snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now + boxes = virtualref_boxes + virtualizable_boxes + else: + boxes = virtualref_boxes[:] + snapshot = Snapshot(snapshot, boxes) storage.rd_snapshot = snapshot class Numbering(object): @@ -182,6 +190,7 @@ n += 1 liveboxes[box] = tagged nums[i] = tagged + # numb = Numbering(numb1, nums) self.numberings[snapshot] = numb, liveboxes, v return numb, liveboxes.copy(), v @@ -388,10 +397,10 @@ class AbstractVirtualInfo(object): - def allocate(self, metainterp): - raise NotImplementedError - def setfields(self, metainterp, box, fn_decode_box): - raise NotImplementedError + #def allocate(self, metainterp): + # raise NotImplementedError + #def setfields(self, decoder, struct): + # raise NotImplementedError def equals(self, fieldnums): return tagged_list_eq(self.fieldnums, fieldnums) def set_content(self, fieldnums): @@ -405,12 +414,11 @@ self.fielddescrs = fielddescrs #self.fieldnums = ... - def setfields(self, metainterp, box, fn_decode_box): + @specialize.argtype(1) + def setfields(self, decoder, struct): for i in range(len(self.fielddescrs)): - fieldbox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETFIELD_GC, - self.fielddescrs[i], - box, fieldbox) + descr = self.fielddescrs[i] + decoder.setfield(descr, struct, self.fieldnums[i]) def debug_prints(self): assert len(self.fielddescrs) == len(self.fieldnums) @@ -424,9 +432,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.known_class = known_class - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - None, self.known_class) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_with_vtable(self.known_class) def debug_prints(self): debug_print("\tvirtualinfo", self.known_class.repr_rpython()) @@ -437,8 +445,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.typedescr = typedescr - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW, self.typedescr) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_struct(self.typedescr) def debug_prints(self): debug_print("\tvstructinfo", self.typedescr.repr_rpython()) @@ -449,117 +458,457 @@ self.arraydescr = arraydescr #self.fieldnums = ... - def allocate(self, metainterp): + @specialize.argtype(1) + def allocate(self, decoder): length = len(self.fieldnums) - return metainterp.execute_and_record(rop.NEW_ARRAY, - self.arraydescr, - ConstInt(length)) - - def setfields(self, metainterp, box, fn_decode_box): - for i in range(len(self.fieldnums)): - itembox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETARRAYITEM_GC, - self.arraydescr, - box, ConstInt(i), itembox) + return decoder.allocate_array(self.arraydescr, length) + + @specialize.argtype(1) + def setfields(self, decoder, array): + arraydescr = self.arraydescr + length = len(self.fieldnums) + # NB. the check for the kind of array elements is moved out of the loop + if arraydescr.is_array_of_pointers(): + for i in range(length): + decoder.setarrayitem_ref(arraydescr, array, i, + self.fieldnums[i]) + elif arraydescr.is_array_of_floats(): + for i in range(length): + decoder.setarrayitem_float(arraydescr, array, i, + self.fieldnums[i]) + else: + for i in range(length): + decoder.setarrayitem_int(arraydescr, array, i, + self.fieldnums[i]) def debug_prints(self): debug_print("\tvarrayinfo", self.arraydescr) for i in self.fieldnums: debug_print("\t\t", str(untag(i))) +# ____________________________________________________________ -def rebuild_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - frameinfo = storage.rd_frame_info_list - while True: - env = resumereader.consume_boxes() - f = metainterp.newframe(frameinfo.jitcode) - f.setup_resume_at_op(frameinfo.pc, frameinfo.exception_target, env) - frameinfo = frameinfo.prev - if frameinfo is None: - break - metainterp.framestack.reverse() - return virtualizable_boxes, virtualref_boxes - -def force_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - return virtualizable_boxes, virtualref_boxes, resumereader.virtuals - - -class ResumeDataReader(object): +class AbstractResumeDataReader(object): + """A base mixin containing the logic to reconstruct virtuals out of + guard failure. There are two implementations of this mixin: + ResumeDataBoxReader for when we are compiling (i.e. when we have a + metainterp), and ResumeDataDirectReader for when we are merely + blackholing and want the best performance. + """ + _mixin_ = True virtuals = None + virtual_default = None - def __init__(self, storage, liveboxes, metainterp=None): + def _init(self, cpu, storage): + self.cpu = cpu self.cur_numb = storage.rd_numb self.consts = storage.rd_consts - self.liveboxes = liveboxes - self.cpu = metainterp.cpu - self._prepare_virtuals(metainterp, storage.rd_virtuals) - self._prepare_pendingfields(metainterp, storage.rd_pendingfields) - def _prepare_virtuals(self, metainterp, virtuals): + def _prepare(self, storage): + self._prepare_virtuals(storage.rd_virtuals) + self._prepare_pendingfields(storage.rd_pendingfields) + + def _prepare_virtuals(self, virtuals): if virtuals: - v = metainterp._already_allocated_resume_virtuals - if v is not None: - self.virtuals = v - return - self.virtuals = [None] * len(virtuals) + self.virtuals = [self.virtual_default] * len(virtuals) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - self.virtuals[i] = vinfo.allocate(metainterp) + self.virtuals[i] = vinfo.allocate(self) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - vinfo.setfields(metainterp, self.virtuals[i], - self._decode_box) + vinfo.setfields(self, self.virtuals[i]) - def _prepare_pendingfields(self, metainterp, pendingfields): - if pendingfields: - if metainterp._already_allocated_resume_virtuals is not None: - return + def _prepare_pendingfields(self, pendingfields): + if pendingfields is not None: for descr, num, fieldnum in pendingfields: - box = self._decode_box(num) - fieldbox = self._decode_box(fieldnum) - metainterp.execute_and_record(rop.SETFIELD_GC, - descr, box, fieldbox) - - def consume_boxes(self): - numb = self.cur_numb - assert numb is not None - nums = numb.nums - n = len(nums) - boxes = [None] * n - for i in range(n): - boxes[i] = self._decode_box(nums[i]) - self.cur_numb = numb.prev - return boxes + struct = self.decode_ref(num) + self.setfield(descr, struct, fieldnum) + + def _prepare_next_section(self, info): + # Use info.enumerate_vars(), normally dispatching to + # pypy.jit.codewriter.jitcode. Some tests give a different 'info'. + info.enumerate_vars(self._callback_i, + self._callback_r, + self._callback_f, + self.unique_id) # <-- annotation hack + self.cur_numb = self.cur_numb.prev + + def _callback_i(self, index, register_index): + value = self.decode_int(self.cur_numb.nums[index]) + self.write_an_int(register_index, value) + + def _callback_r(self, index, register_index): + value = self.decode_ref(self.cur_numb.nums[index]) + self.write_a_ref(register_index, value) + + def _callback_f(self, index, register_index): + value = self.decode_float(self.cur_numb.nums[index]) + self.write_a_float(register_index, value) + + def done(self): + self.cpu.clear_latest_values(self.cpu.get_latest_value_count()) + +# ---------- when resuming for pyjitpl.py, make boxes ---------- + +def rebuild_from_resumedata(metainterp, storage, virtualizable_info): + resumereader = ResumeDataBoxReader(storage, metainterp) + boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info) + virtualizable_boxes, virtualref_boxes = boxes + frameinfo = storage.rd_frame_info_list + while True: + f = metainterp.newframe(frameinfo.jitcode) + f.setup_resume_at_op(frameinfo.pc) + resumereader.consume_boxes(f.get_current_position_info(), + f.registers_i, f.registers_r, f.registers_f) + frameinfo = frameinfo.prev + if frameinfo is None: + break + metainterp.framestack.reverse() + resumereader.done() + return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes + +class ResumeDataBoxReader(AbstractResumeDataReader): + unique_id = lambda: None - def _decode_box(self, tagged): + def __init__(self, storage, metainterp): + self._init(metainterp.cpu, storage) + self.metainterp = metainterp + self.liveboxes = [None] * metainterp.cpu.get_latest_value_count() + self._prepare(storage) + + def consume_boxes(self, info, boxes_i, boxes_r, boxes_f): + self.boxes_i = boxes_i + self.boxes_r = boxes_r + self.boxes_f = boxes_f + self._prepare_next_section(info) + + def consume_virtualizable_boxes(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], and use it to know how many + # boxes of which type we have to return. This does not write + # anything into the virtualizable. + virtualizablebox = self.decode_ref(nums[-1]) + virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox) + return vinfo.load_list_of_boxes(virtualizable, self, nums) + + def consume_virtualref_boxes(self, nums, end): + # Returns a list of boxes, assumed to be all BoxPtrs. + # We leave up to the caller to call vrefinfo.continue_tracing(). + assert (end & 1) == 0 + return [self.decode_ref(nums[i]) for i in range(end)] + + def consume_vref_and_vable_boxes(self, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if vinfo is None: + virtualizable_boxes = None + end = len(nums) + else: + virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums) + end = len(nums) - len(virtualizable_boxes) + virtualref_boxes = self.consume_virtualref_boxes(nums, end) + return virtualizable_boxes, virtualref_boxes + + def allocate_with_vtable(self, known_class): + return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE, + None, known_class) + + def allocate_struct(self, typedescr): + return self.metainterp.execute_and_record(rop.NEW, typedescr) + + def allocate_array(self, arraydescr, length): + return self.metainterp.execute_and_record(rop.NEW_ARRAY, + arraydescr, ConstInt(length)) + + def setfield(self, descr, structbox, fieldnum): + if descr.is_pointer_field(): + kind = REF + elif descr.is_float_field(): + kind = FLOAT + else: + kind = INT + fieldbox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETFIELD_GC, descr, + structbox, fieldbox) + + def setarrayitem_int(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, INT) + + def setarrayitem_ref(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, REF) + + def setarrayitem_float(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, FLOAT) + + def setarrayitem(self, arraydescr, arraybox, index, fieldnum, kind): + itembox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETARRAYITEM_GC, + arraydescr, arraybox, + ConstInt(index), itembox) + + def decode_int(self, tagged): + return self.decode_box(tagged, INT) + def decode_ref(self, tagged): + return self.decode_box(tagged, REF) + def decode_float(self, tagged): + return self.decode_box(tagged, FLOAT) + + def decode_box(self, tagged, kind): num, tag = untag(tagged) if tag == TAGCONST: if tagged_eq(tagged, NULLREF): - return self.cpu.ts.CONST_NULL - return self.consts[num] + box = self.cpu.ts.CONST_NULL + else: + box = self.consts[num] elif tag == TAGVIRTUAL: virtuals = self.virtuals assert virtuals is not None - return virtuals[num] + box = virtuals[num] + elif tag == TAGINT: + box = ConstInt(num) + else: + assert tag == TAGBOX + box = self.liveboxes[num] + if box is None: + box = self.load_box_from_cpu(num, kind) + assert box.type == kind + return box + + def load_box_from_cpu(self, num, kind): + if num < 0: + num += len(self.liveboxes) + assert num >= 0 + if kind == INT: + box = BoxInt(self.cpu.get_latest_value_int(num)) + elif kind == REF: + box = BoxPtr(self.cpu.get_latest_value_ref(num)) + elif kind == FLOAT: + box = BoxFloat(self.cpu.get_latest_value_float(num)) + else: + assert 0, "bad kind: %d" % ord(kind) + self.liveboxes[num] = box + return box + + def decode_box_of_type(self, TYPE, tagged): + kind = getkind(TYPE) + if kind == 'int': kind = INT + elif kind == 'ref': kind = REF + elif kind == 'float': kind = FLOAT + else: raise AssertionError(kind) + return self.decode_box(tagged, kind) + decode_box_of_type._annspecialcase_ = 'specialize:arg(1)' + + def write_an_int(self, index, box): + self.boxes_i[index] = box + def write_a_ref(self, index, box): + self.boxes_r[index] = box + def write_a_float(self, index, box): + self.boxes_f[index] = box + +# ---------- when resuming for blackholing, get direct values ---------- + +def blackhole_from_resumedata(blackholeinterpbuilder, storage, + all_virtuals=None): + resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, + all_virtuals) + vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + # + # First get a chain of blackhole interpreters whose length is given + # by the depth of rd_frame_info_list. The first one we get must be + # the bottom one, i.e. the last one in the chain, in order to make + # the comment in BlackholeInterpreter.setposition() valid. + nextbh = None + frameinfo = storage.rd_frame_info_list + while True: + curbh = blackholeinterpbuilder.acquire_interp() + curbh.nextblackholeinterp = nextbh + nextbh = curbh + frameinfo = frameinfo.prev + if frameinfo is None: + break + firstbh = nextbh + # + # Now fill the blackhole interpreters with resume data. + curbh = firstbh + frameinfo = storage.rd_frame_info_list + while True: + curbh.setposition(frameinfo.jitcode, frameinfo.pc) + resumereader.consume_one_section(curbh) + curbh = curbh.nextblackholeinterp + frameinfo = frameinfo.prev + if frameinfo is None: + break + resumereader.done() + return firstbh + +def force_from_resumedata(metainterp_sd, storage): + resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) + resumereader.handling_async_forcing() + vinfo = metainterp_sd.virtualizable_info + vrefinfo = metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + return resumereader.virtuals + +class ResumeDataDirectReader(AbstractResumeDataReader): + unique_id = lambda: None + virtual_default = lltype.nullptr(llmemory.GCREF.TO) + resume_after_guard_not_forced = 0 + # 0: not a GUARD_NOT_FORCED + # 1: in handle_async_forcing + # 2: resuming from the GUARD_NOT_FORCED + + def __init__(self, cpu, storage, all_virtuals=None): + self._init(cpu, storage) + if all_virtuals is None: # common case + self._prepare(storage) + else: + # special case for resuming after a GUARD_NOT_FORCED: we already + # have the virtuals + self.resume_after_guard_not_forced = 2 + self.virtuals = all_virtuals + + def handling_async_forcing(self): + self.resume_after_guard_not_forced = 1 + + def consume_one_section(self, blackholeinterp): + self.blackholeinterp = blackholeinterp + info = blackholeinterp.get_current_position_info() + self._prepare_next_section(info) + + def consume_virtualref_info(self, vrefinfo, nums, end): + # we have to decode a list of references containing pairs + # [..., virtual, vref, ...] stopping at 'end' + assert (end & 1) == 0 + for i in range(0, end, 2): + virtual = self.decode_ref(nums[i]) + vref = self.decode_ref(nums[i+1]) + # For each pair, we store the virtual inside the vref. + vrefinfo.continue_tracing(vref, virtual) + + def consume_vable_info(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], load all other values + # from the CPU stack, and copy them into the virtualizable + if vinfo is None: + return len(nums) + virtualizable = self.decode_ref(nums[-1]) + virtualizable = vinfo.cast_gcref_to_vtype(virtualizable) + if self.resume_after_guard_not_forced == 1: + # in the middle of handle_async_forcing() + assert virtualizable.vable_token + virtualizable.vable_token = vinfo.TOKEN_NONE + else: + # just jumped away from assembler (case 4 in the comment in + # virtualizable.py) into tracing (case 2); check that vable_token + # is and stays 0. Note the call to reset_vable_token() in + # warmstate.py. + assert not virtualizable.vable_token + return vinfo.write_from_resume_data_partial(virtualizable, self, nums) + + def load_value_of_type(self, TYPE, tagged): + from pypy.jit.metainterp.warmstate import specialize_value + kind = getkind(TYPE) + if kind == 'int': + x = self.decode_int(tagged) + elif kind == 'ref': + x = self.decode_ref(tagged) + elif kind == 'float': + x = self.decode_float(tagged) + else: + raise AssertionError(kind) + return specialize_value(TYPE, x) + load_value_of_type._annspecialcase_ = 'specialize:arg(1)' + + def consume_vref_and_vable(self, vrefinfo, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if self.resume_after_guard_not_forced != 2: + end_vref = self.consume_vable_info(vinfo, nums) + self.consume_virtualref_info(vrefinfo, nums, end_vref) + + def allocate_with_vtable(self, known_class): + from pypy.jit.metainterp.executor import exec_new_with_vtable + return exec_new_with_vtable(self.cpu, known_class) + + def allocate_struct(self, typedescr): + return self.cpu.bh_new(typedescr) + + def allocate_array(self, arraydescr, length): + return self.cpu.bh_new_array(arraydescr, length) + + def setfield(self, descr, struct, fieldnum): + if descr.is_pointer_field(): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setfield_gc_r(struct, descr, newvalue) + elif descr.is_float_field(): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setfield_gc_f(struct, descr, newvalue) + else: + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setfield_gc_i(struct, descr, newvalue) + + def setarrayitem_int(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setarrayitem_gc_i(arraydescr, array, index, newvalue) + + def setarrayitem_ref(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setarrayitem_gc_r(arraydescr, array, index, newvalue) + + def setarrayitem_float(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setarrayitem_gc_f(arraydescr, array, index, newvalue) + + def decode_int(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getint() elif tag == TAGINT: - return ConstInt(num) + return num else: assert tag == TAGBOX - return self.liveboxes[num] + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_int(num) + + def decode_ref(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + if tagged_eq(tagged, NULLREF): + return self.cpu.ts.NULLREF + return self.consts[num].getref_base() + elif tag == TAGVIRTUAL: + virtuals = self.virtuals + assert virtuals is not None + return virtuals[num] + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_ref(num) + + def decode_float(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getfloat() + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_float(num) + + def write_an_int(self, index, int): + self.blackholeinterp.setarg_i(index, int) + + def write_a_ref(self, index, ref): + self.blackholeinterp.setarg_r(index, ref) + + def write_a_float(self, index, float): + self.blackholeinterp.setarg_f(index, float) # ____________________________________________________________ @@ -576,7 +925,7 @@ except AttributeError: jitcodename = str(compute_unique_id(frameinfo.jitcode)) debug_print('\tjitcode/pc', jitcodename, - frameinfo.pc, frameinfo.exception_target, + frameinfo.pc, 'at', compute_unique_id(frameinfo)) frameinfo = frameinfo.prev numb = storage.rd_numb Modified: pypy/trunk/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/trunk/pypy/jit/metainterp/simple_optimize.py Tue Jun 8 23:42:50 2010 @@ -10,12 +10,16 @@ def transform(op): from pypy.jit.metainterp.history import AbstractDescr # change ARRAYCOPY to call, so we don't have to pass around - # unnecessary information to the backend + # unnecessary information to the backend. Do the same with VIRTUAL_REF_*. if op.opnum == rop.ARRAYCOPY: descr = op.args[0] assert isinstance(descr, AbstractDescr) - return ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) - return op + op = ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) + elif op.opnum == rop.VIRTUAL_REF: + op = ResOperation(rop.SAME_AS, [op.args[0]], op.result) + elif op.opnum == rop.VIRTUAL_REF_FINISH: + return [] + return [op] def optimize_loop(metainterp_sd, old_loops, loop): if old_loops: @@ -35,7 +39,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, memo) newboxes = modifier.finish(EMPTY_VALUES) descr.store_final_boxes(op, newboxes) - newoperations.append(transform(op)) + newoperations.extend(transform(op)) loop.operations = newoperations return None Modified: pypy/trunk/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/specnode.py (original) +++ pypy/trunk/pypy/jit/metainterp/specnode.py Tue Jun 8 23:42:50 2010 @@ -57,7 +57,8 @@ from pypy.jit.metainterp import executor, history, resoperation for ofs, subspecnode in self.fields: assert isinstance(ofs, history.AbstractDescr) - fieldbox = executor.execute(cpu, resoperation.rop.GETFIELD_GC, + fieldbox = executor.execute(cpu, None, + resoperation.rop.GETFIELD_GC, ofs, valuebox) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -95,7 +96,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp import executor, history, resoperation for i in range(len(self.items)): - itembox = executor.execute(cpu, resoperation.rop.GETARRAYITEM_GC, + itembox = executor.execute(cpu, None, + resoperation.rop.GETARRAYITEM_GC, self.arraydescr, valuebox, history.ConstInt(i)) subspecnode = self.items[i] Modified: pypy/trunk/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/oparser.py Tue Jun 8 23:42:50 2010 @@ -4,10 +4,11 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\ - ConstAddr, ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ + ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ LoopToken from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.typesystem import llhelper +from pypy.jit.codewriter.heaptracker import adr2int from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llstr @@ -74,8 +75,7 @@ return ConstPtr(obj) else: assert typ == 'class' - return ConstAddr(llmemory.cast_ptr_to_adr(obj), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(obj))) else: if typ == 'ptr': return ConstObj(obj) Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Tue Jun 8 23:42:50 2010 @@ -4,30 +4,97 @@ from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp import support, codewriter, pyjitpl, history -from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy +from pypy.jit.metainterp import pyjitpl, history +from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy from pypy import conftest from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype -def _get_bare_metainterp(func, values, CPUClass, type_system, - listops=False): - from pypy.annotation.policy import AnnotatorPolicy - from pypy.annotation.model import lltype_to_annotation - from pypy.rpython.test.test_llinterp import gengraph +def _get_jitcodes(testself, CPUClass, func, values, type_system): + from pypy.jit.codewriter import support, codewriter + from pypy.jit.metainterp import simple_optimize - rtyper = support.annotate(func, values, type_system=type_system) + class FakeWarmRunnerState: + def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): + pass + + # pick the optimizer this way + optimize_loop = staticmethod(simple_optimize.optimize_loop) + optimize_bridge = staticmethod(simple_optimize.optimize_bridge) + + trace_limit = sys.maxint + debug_level = 2 + func._jit_unroll_safe_ = True + rtyper = support.annotate(func, values, type_system=type_system) + graphs = rtyper.annotator.translator.graphs stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - graphs = rtyper.annotator.translator.graphs - opt = history.Options(listops=listops) - metainterp_sd = pyjitpl.MetaInterpStaticData(graphs[0], cpu, stats, opt) - metainterp_sd.finish_setup(optimizer="bogus") + cw = codewriter.CodeWriter(cpu, graphs[0]) + testself.cw = cw + cw.find_all_graphs(JitPolicy()) + # + testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate.cpu = cpu + if hasattr(testself, 'finish_setup_for_interp_operations'): + testself.finish_setup_for_interp_operations() + # + cw.make_jitcodes(verbose=True) + +def _run_with_blackhole(testself, args): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + cw = testself.cw + blackholeinterpbuilder = BlackholeInterpBuilder(cw) + blackholeinterp = blackholeinterpbuilder.acquire_interp() + count_i = count_r = count_f = 0 + for value in args: + T = lltype.typeOf(value) + if T == lltype.Signed: + blackholeinterp.setarg_i(count_i, value) + count_i += 1 + elif T == llmemory.GCREF: + blackholeinterp.setarg_r(count_r, value) + count_r += 1 + elif T == lltype.Float: + blackholeinterp.setarg_f(count_f, value) + count_f += 1 + else: + raise TypeError(T) + blackholeinterp.setposition(cw.mainjitcode, 0) + blackholeinterp.run() + return blackholeinterp._final_result_anytype() + +def _run_with_pyjitpl(testself, args): + + class DoneWithThisFrame(Exception): + pass + + class DoneWithThisFrameRef(DoneWithThisFrame): + def __init__(self, cpu, *args): + DoneWithThisFrame.__init__(self, *args) + + cw = testself.cw + opt = history.Options(listops=True) + metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) + metainterp_sd.finish_setup(cw, optimizer="bogus") + metainterp_sd.state = testself.warmrunnerstate + metainterp_sd.state.cpu = metainterp_sd.cpu metainterp = pyjitpl.MetaInterp(metainterp_sd) - return metainterp, rtyper + metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame + metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef + metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame + testself.metainterp = metainterp + try: + metainterp.compile_and_run_once(*args) + except DoneWithThisFrame, e: + #if conftest.option.view: + # metainterp.stats.view() + return e.args[0] + else: + raise Exception("FAILED") + class JitMixin: basic = True @@ -63,56 +130,14 @@ return ll_meta_interp(*args, **kwds) def interp_operations(self, f, args, **kwds): - from pypy.jit.metainterp import simple_optimize - - class DoneWithThisFrame(Exception): - pass - - class DoneWithThisFrameRef(DoneWithThisFrame): - def __init__(self, cpu, *args): - DoneWithThisFrame.__init__(self, *args) - - class FakeWarmRunnerState: - def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): - pass - - # pick the optimizer this way - optimize_loop = staticmethod(simple_optimize.optimize_loop) - optimize_bridge = staticmethod(simple_optimize.optimize_bridge) - - trace_limit = sys.maxint - debug_level = 2 - - metainterp, rtyper = _get_bare_metainterp(f, args, self.CPUClass, - self.type_system, - **kwds) - metainterp.staticdata.state = FakeWarmRunnerState() - metainterp.staticdata.state.cpu = metainterp.staticdata.cpu - if hasattr(self, 'finish_metainterp_for_interp_operations'): - self.finish_metainterp_for_interp_operations(metainterp) - portal_graph = rtyper.annotator.translator.graphs[0] - cw = codewriter.CodeWriter(rtyper) - - graphs = cw.find_all_graphs(portal_graph, JitPolicy(), - self.CPUClass.supports_floats) - cw._start(metainterp.staticdata, None) - portal_graph.func._jit_unroll_safe_ = True - maingraph = cw.make_one_bytecode((portal_graph, None), False) - cw.finish_making_bytecodes() - metainterp.staticdata.portal_code = maingraph - metainterp.staticdata._class_sizes = cw.class_sizes - metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame - metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef - metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame - self.metainterp = metainterp - try: - metainterp.compile_and_run_once(*args) - except DoneWithThisFrame, e: - #if conftest.option.view: - # metainterp.stats.view() - return e.args[0] - else: - raise Exception("FAILED") + # get the JitCodes for the function f + _get_jitcodes(self, self.CPUClass, f, args, self.type_system) + # try to run it with blackhole.py + result1 = _run_with_blackhole(self, args) + # try to run it with pyjitpl.py + result2 = _run_with_pyjitpl(self, args) + assert result1 == result2 + return result1 def check_history(self, expected=None, **isns): # this can be used after calling meta_interp @@ -151,7 +176,7 @@ class OOJitMixin(JitMixin): type_system = 'ootype' - CPUClass = runner.OOtypeCPU + #CPUClass = runner.OOtypeCPU def setup_class(cls): py.test.skip("ootype tests skipped for now") @@ -204,9 +229,11 @@ from pypy.rlib.rarithmetic import r_uint def f(a, b): + a = r_uint(a) + b = r_uint(b) return a/b - res = self.interp_operations(f, [r_uint(4), r_uint(3)]) + res = self.interp_operations(f, [4, 3]) assert res == 1 def test_direct_call(self): @@ -339,6 +366,38 @@ assert res == 42 self.check_operations_history(int_add=0, int_mul=0, call=0) + def test_constfold_call_pure(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + n -= externfn(m) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + + def test_constfold_call_pure_2(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + class V: + def __init__(self, value): + self.value = value + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + v = V(m) + n -= externfn(v.value) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) class X(object): @@ -513,6 +572,39 @@ res = self.interp_operations(f, [15]) assert res == -1 + def test_int_add_ovf(self): + def f(x, y): + try: + return ovfcheck(x + y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -98 + res = self.interp_operations(f, [1, sys.maxint]) + assert res == -42 + + def test_int_sub_ovf(self): + def f(x, y): + try: + return ovfcheck(x - y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -102 + res = self.interp_operations(f, [1, -sys.maxint]) + assert res == -42 + + def test_int_mul_ovf(self): + def f(x, y): + try: + return ovfcheck(x * y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -200 + res = self.interp_operations(f, [-3, sys.maxint//2]) + assert res == -42 + def test_mod_ovf(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) def f(n, x, y): @@ -523,6 +615,7 @@ return n res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + self.check_loops(call=0) def test_abs(self): myjitdriver = JitDriver(greens = [], reds = ['i', 't']) @@ -581,10 +674,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) def test_bridge_from_interpreter_2(self): # one case for backend - computing of framesize on guard failure @@ -731,21 +823,26 @@ def test_zerodivisionerror(self): # test the case of exception-raising operation that is not delegated # to the backend at all: ZeroDivisionError - from pypy.rpython.lltypesystem.lloperation import llop # def f(n): + assert n >= 0 try: - return llop.int_mod_ovf_zer(lltype.Signed, 5, n) + return ovfcheck(5 % n) except ZeroDivisionError: return -666 + except OverflowError: + return -777 res = self.interp_operations(f, [0]) assert res == -666 # def f(n): + assert n >= 0 try: - return llop.int_floordiv_ovf_zer(lltype.Signed, 6, n) + return ovfcheck(6 // n) except ZeroDivisionError: return -667 + except OverflowError: + return -778 res = self.interp_operations(f, [0]) assert res == -667 @@ -795,7 +892,7 @@ assert not res def test_isinstance_2(self): - driver = JitDriver(greens = [], reds = ['x', 'n', 'sum']) + driver = JitDriver(greens = [], reds = ['n', 'sum', 'x']) class A: pass class B(A): @@ -836,7 +933,9 @@ return obj.a res = self.interp_operations(fn, [1]) assert res == 1 - self.check_operations_history(guard_class=0, instanceof=0) + self.check_operations_history(guard_class=0) + if self.type_system == 'ootype': + self.check_operations_history(instanceof=0) def test_r_dict(self): from pypy.rlib.objectmodel import r_dict @@ -1017,10 +1116,10 @@ def test_residual_external_call(self): import math - myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res']) def f(x, y): x = float(x) - res = 0 + res = 0.0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) @@ -1259,7 +1358,7 @@ self.check_loops(call=1) def test_bug_optimizeopt_mutates_ops(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'a', 'const']) + myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a']) class A(object): pass class B(A): @@ -1326,6 +1425,16 @@ # this checks that the logic triggered by make_a_counter_per_value() # works and prevents generating tons of bridges + def test_swap_values(self): + def f(x, y): + if x > 5: + x, y = y, x + return x - y + res = self.interp_operations(f, [10, 2]) + assert res == -8 + res = self.interp_operations(f, [3, 2]) + assert res == 1 + class TestOOtype(BasicTests, OOJitMixin): @@ -1426,33 +1535,47 @@ from pypy.rpython.lltypesystem import lltype TP = lltype.Struct('x') - def f(p1, p2): + def f(i1, i2): + p1 = prebuilt[i1] + p2 = prebuilt[i2] a = p1 is p2 b = p1 is not p2 c = bool(p1) d = not bool(p2) return 1000*a + 100*b + 10*c + d - x = lltype.malloc(TP, flavor='raw') - expected = f(x, x) - assert self.interp_operations(f, [x, x]) == expected - lltype.free(x, flavor='raw') + prebuilt = [lltype.malloc(TP, flavor='raw')] * 2 + expected = f(0, 1) + assert self.interp_operations(f, [0, 1]) == expected def test_casts(self): + py.test.skip("xxx fix or kill") if not self.basic: py.test.skip("test written in a style that " "means it's frontend only") - from pypy.rpython.lltypesystem import lltype, llmemory - - TP = lltype.GcStruct('x') + from pypy.rpython.lltypesystem import lltype, llmemory, rffi + + TP = lltype.GcStruct('S1') def f(p): n = lltype.cast_ptr_to_int(p) return n - x = lltype.malloc(TP) - res = self.interp_operations(f, [x]) - expected = self.metainterp.cpu.do_cast_ptr_to_int( - history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))).value - assert res == expected + xref = lltype.cast_opaque_ptr(llmemory.GCREF, x) + res = self.interp_operations(f, [xref]) + y = llmemory.cast_ptr_to_adr(x) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) + # + TP = lltype.Struct('S2') + prebuilt = [lltype.malloc(TP, immortal=True), + lltype.malloc(TP, immortal=True)] + def f(x): + p = prebuilt[x] + n = lltype.cast_ptr_to_int(p) + return n + res = self.interp_operations(f, [1]) + y = llmemory.cast_ptr_to_adr(prebuilt[1]) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) def test_collapsing_ptr_eq(self): S = lltype.GcStruct('S') Modified: pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py Tue Jun 8 23:42:50 2010 @@ -1,87 +1,211 @@ +import py from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp import pyjitpl +from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder +from pypy.jit.metainterp.blackhole import BlackholeInterpreter +from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl +from pypy.jit.metainterp import history, pyjitpl +from pypy.jit.codewriter.assembler import JitCode +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.llinterp import LLException -class BlackholeTests(object): - - def meta_interp(self, *args): - def counting_init(frame, metainterp, jitcode, greenkey=None): - previnit(frame, metainterp, jitcode, greenkey) - self.seen_frames.append(jitcode.name) +class FakeCodeWriter: + pass +class FakeAssembler: + pass +class FakeCPU: + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert func == 321 + assert calldescr == "" + if args_i[0] < 0: + raise LLException("etype", "evalue") + return args_i[0] * 2 + +def getblackholeinterp(insns, descrs=[]): + cw = FakeCodeWriter() + cw.cpu = FakeCPU() + cw.assembler = FakeAssembler() + cw.assembler.insns = insns + cw.assembler.descrs = descrs + builder = BlackholeInterpBuilder(cw) + return builder.acquire_interp() + +def test_simple(): + jitcode = JitCode("test") + jitcode.setup("\x00\x00\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_add/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0, 40) + blackholeinterp.setarg_i(1, 2) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_const(): + jitcode = JitCode("test") + jitcode.setup("\x00\x30\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_sub/ci>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 6) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_bigconst(): + jitcode = JitCode("test") + jitcode.setup("\x00\xFD\x01\x02" + "\x01\x02", + [666, 666, 10042, 666]) + blackholeinterp = getblackholeinterp({'int_sub/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 10000) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_loop(): + jitcode = JitCode("test") + jitcode.setup("\x00\x16\x02\x10\x00" # L1: goto_if_not_int_gt %i0, 2, L2 + "\x01\x17\x16\x17" # int_add %i1, %i0, %i1 + "\x02\x16\x01\x16" # int_sub %i0, $1, %i0 + "\x03\x00\x00" # goto L1 + "\x04\x17", # L2: int_return %i1 + []) + blackholeinterp = getblackholeinterp({'goto_if_not_int_gt/icL': 0, + 'int_add/ii>i': 1, + 'int_sub/ic>i': 2, + 'goto/L': 3, + 'int_return/i': 4}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x16, 6) # %i0 + blackholeinterp.setarg_i(0x17, 100) # %i1 + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 100+6+5+4+3 + +def test_simple_exception(): + jitcode = JitCode("test") + jitcode.setup( # residual_call_ir_i $<* fn g>, , I[%i9], R[], %i8 + "\x01\xFF\x00\x00\x01\x09\x00\x08" + "\x00\x0D\x00" # catch_exception L1 + "\x02\x08" # int_return %i8 + "\x03\x2A", # L1: int_return $42 + [321]) # <-- address of the function g + blackholeinterp = getblackholeinterp({'catch_exception/L': 0, + 'residual_call_ir_i/idIR>i': 1, + 'int_return/i': 2, + 'int_return/c': 3}, + [""]) + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, 100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 200 + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, -100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_convert_and_run_from_pyjitpl(): + class MyMIFrame: + jitcode = JitCode("test") + jitcode.setup("\xFF" # illegal instruction + "\x00\x00\x01\x02" # int_add/ii>i + "\x01\x02", # int_return/i + [], + num_regs_i=3, num_regs_r=0, num_regs_f=0) + pc = 1 + registers_i = [history.BoxInt(40), history.ConstInt(2), None] + class MyMetaInterp: + class staticdata: + result_type = 'int' + class profiler: + @staticmethod + def start_blackhole(): pass + @staticmethod + def end_blackhole(): pass + class DoneWithThisFrameInt(Exception): + pass + last_exc_value_box = None + framestack = [MyMIFrame()] + MyMetaInterp.staticdata.blackholeinterpbuilder = getblackholeinterp( + {'int_add/ii>i': 0, 'int_return/i': 1}).builder + MyMetaInterp.staticdata.blackholeinterpbuilder.metainterp_sd = \ + MyMetaInterp.staticdata + # + d = py.test.raises(MyMetaInterp.staticdata.DoneWithThisFrameInt, + convert_and_run_from_pyjitpl, MyMetaInterp()) + assert d.value.args == (42,) + + +class TestBlackhole(LLJitMixin): + + def test_blackholeinterp_cache(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + def choices(x): + if x == 2: return 10 + if x == 3: return 199 + if x == 4: return 124 + if x == 5: return -521 + if x == 6: return 8917 + if x == 7: return -387 + return 34871 + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + y += choices(x) + x -= 1 + return y # - previnit = pyjitpl.MIFrame.__init__.im_func + seen = [] + def my_copy_constants(self, *args): + seen.append(1) + return org_copy_constants(self, *args) + org_copy_constants = BlackholeInterpreter.copy_constants + BlackholeInterpreter.copy_constants = my_copy_constants try: - self.seen_frames = [] - pyjitpl.MIFrame.__init__ = counting_init - return super(BlackholeTests, self).meta_interp(*args) + res = self.meta_interp(f, [7], repeat=7) finally: - pyjitpl.MIFrame.__init__ = previnit - - def test_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - return g() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_indirect_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - call = h - else: - call = g - return call() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_oosends_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - class A: - def meth(self): - return 42 - class B(A): - def meth(self): - return 45 - class C(A): - def meth(self): - return 64 - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - x = B() - else: - x = C() - return x.meth() - res = self.meta_interp(f, [7]) - assert res == 64 - assert self.seen_frames == ['f', 'f'] - - -class TestLLtype(BlackholeTests, LLJitMixin): - pass - -class TestOOtype(BlackholeTests, OOJitMixin): - pass + BlackholeInterpreter.copy_constants = org_copy_constants + # + assert res == sum([choices(x) for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 + assert len(seen) == 2 * 3 + + def test_blackholeinterp_cache_exc(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + class FooError(Exception): + def __init__(self, num): + self.num = num + def choices(x): + if x == 2: raise FooError(10) + if x == 3: raise FooError(199) + if x == 4: raise FooError(124) + if x == 5: raise FooError(-521) + if x == 6: raise FooError(8917) + if x == 7: raise FooError(-387) + raise FooError(34871) + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + try: + choices(x) + except FooError, e: + y += e.num + x -= 1 + return y + res = self.meta_interp(f, [7], repeat=7) + assert res == sum([py.test.raises(FooError, choices, x).value.num + for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 Modified: pypy/trunk/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_compile.py Tue Jun 8 23:42:50 2010 @@ -2,7 +2,8 @@ from pypy.jit.metainterp.history import BoxInt from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop -from pypy.jit.metainterp.compile import ResumeGuardDescr, ResumeGuardCounters +from pypy.jit.metainterp.compile import ResumeGuardDescr +from pypy.jit.metainterp.compile import ResumeGuardCountersInt from pypy.jit.metainterp import optimize, jitprof, typesystem from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin @@ -107,49 +108,49 @@ def test_resume_guard_counters(): - rgc = ResumeGuardCounters() + rgc = ResumeGuardCountersInt() # fill in the table for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 1 - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 2 assert rgc.counters == [0] * (4-i) + [2] * (1+i) for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 3 # make a distribution: [5, 4, 7, 6, 3] assert rgc.counters == [3, 3, 3, 3, 3] - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 4 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 5 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 4 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 5 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 7 - count = rgc.see(BoxInt(103)) + count = rgc.see_int(103) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 5 assert rgc.counters == [5, 4, 7, 6, 3] # the next new item should throw away 104, as 5 is the middle counter - count = rgc.see(BoxInt(190)) + count = rgc.see_int(190) assert count == 1 assert rgc.counters == [1, 4, 7, 6, 3] # the next new item should throw away 103, as 4 is the middle counter - count = rgc.see(BoxInt(191)) + count = rgc.see_int(191) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 3] # the next new item should throw away 100, as 3 is the middle counter - count = rgc.see(BoxInt(192)) + count = rgc.see_int(192) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 1] Modified: pypy/trunk/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_exception.py Tue Jun 8 23:42:50 2010 @@ -2,7 +2,7 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy class ExceptionTests: @@ -516,11 +516,10 @@ assert res == -1 self.check_tree_loop_count(2) # the loop and the entry path # we get: - # ENTER - compile the new loop - # ENTER (BlackHole) - leave - # ENTER - compile the entry bridge - # ENTER - compile the leaving path (raising MyError) - self.check_enter_count(4) + # ENTER - compile the new loop + # ENTER - compile the entry bridge + # ENTER - compile the leaving path (raising MyError) + self.check_enter_count(3) def test_bridge_from_interpreter_exc_2(self): @@ -556,7 +555,6 @@ optimizer=OPTIMIZER_SIMPLE) assert res == 8 - def test_overflowerror_escapes(self): def g(x): return ovfcheck(x + 1) @@ -570,6 +568,26 @@ res = self.interp_operations(f, [sys.maxint]) assert res == -42 + def test_bug_1(self): + def h(i): + if i > 10: + raise ValueError + if i > 5: + raise KeyError + return 5 + def g(i): + try: + return h(i) + except ValueError: + return 21 + def f(i): + try: + return g(i) + except KeyError: + return 42 + res = self.interp_operations(f, [99]) + assert res == 21 + class MyError(Exception): def __init__(self, n): self.n = n Modified: pypy/trunk/pypy/jit/metainterp/test/test_executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_executor.py Tue Jun 8 23:42:50 2010 @@ -1,60 +1,87 @@ import py import sys, random from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.jit.metainterp.executor import make_execute_list, execute +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.executor import execute_varargs, execute_nonspec from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat from pypy.jit.metainterp.history import AbstractDescr, Box +from pypy.jit.metainterp import history from pypy.jit.backend.model import AbstractCPU class FakeDescr(AbstractDescr): pass -class FakeBox(Box): +class FakeCallDescr(FakeDescr): + def get_return_type(self): + return history.FLOAT + +class FakeFieldDescr(FakeDescr): + def is_pointer_field(self): + return False + def is_float_field(self): + return True + +class FakeArrayDescr(FakeDescr): + def is_array_of_pointers(self): + return False + def is_array_of_floats(self): + return True + +class FakeResultR: + _TYPE = llmemory.GCREF def __init__(self, *args): - self.args = args + self.fakeargs = args + +class FakeMetaInterp: + pass class FakeCPU(AbstractCPU): supports_floats = True - def do_new(self, descr): - return FakeBox('new', descr) - - def do_arraylen_gc(self, box1, descr): - return FakeBox('arraylen_gc', box1, descr) - - def do_setfield_gc(self, box1, box2, descr): - return FakeBox('setfield_gc', box1, box2, descr) + def bh_new(self, descr): + return FakeResultR('new', descr) - def do_setarrayitem_gc(self, box1, box2, box3, descr): - return FakeBox('setarrayitem_gc', box1, box2, box3, descr) + def bh_arraylen_gc(self, descr, array): + assert not array + assert isinstance(descr, FakeDescr) + return 55 + + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + self.fakesetfield = (struct, newvalue, fielddescr) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + self.fakesetarrayitem = (array, index, newvalue, arraydescr) + + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self.fakecalled = (func, calldescr, args_i, args_r, args_f) + return 42.5 - def do_call(self, args, descr): - return FakeBox('call', args, descr) - - def do_strsetitem(self, box1, box2, box3): - return FakeBox('strsetitem', box1, box2, box3) - -make_execute_list(FakeCPU) + def bh_strsetitem(self, string, index, newvalue): + self.fakestrsetitem = (string, index, newvalue) def test_execute(): cpu = FakeCPU() descr = FakeDescr() - box = execute(cpu, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) + box = execute(cpu, None, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) assert box.value == 42 - box = execute(cpu, rop.NEW, descr) - assert box.args == ('new', descr) + box = execute(cpu, None, rop.NEW, descr) + assert box.value.fakeargs == ('new', descr) def test_execute_varargs(): cpu = FakeCPU() - descr = FakeDescr() - argboxes = [BoxInt(321), ConstInt(123)] - box = execute_varargs(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + descr = FakeCallDescr() + argboxes = [BoxInt(99999), BoxInt(321), ConstFloat(2.25), ConstInt(123), + BoxPtr(), BoxFloat(5.5)] + box = execute_varargs(cpu, FakeMetaInterp(), rop.CALL, argboxes, descr) + assert box.value == 42.5 + assert cpu.fakecalled == (99999, descr, [321, 123], + [ConstPtr.value], [2.25, 5.5]) def test_execute_nonspec(): cpu = FakeCPU() @@ -62,33 +89,38 @@ # cases with a descr # arity == -1 argboxes = [BoxInt(321), ConstInt(123)] - box = execute_nonspec(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + box = execute_nonspec(cpu, FakeMetaInterp(), rop.CALL, + argboxes, FakeCallDescr()) + assert box.value == 42.5 # arity == 0 - box = execute_nonspec(cpu, rop.NEW, [], descr) - assert box.args == ('new', descr) + box = execute_nonspec(cpu, None, rop.NEW, [], descr) + assert box.value.fakeargs == ('new', descr) # arity == 1 - box1 = BoxInt(515) - box = execute_nonspec(cpu, rop.ARRAYLEN_GC, [box1], descr) - assert box.args == ('arraylen_gc', box1, descr) + box1 = BoxPtr() + box = execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr) + assert box.value == 55 # arity == 2 - box2 = BoxInt(222) - box = execute_nonspec(cpu, rop.SETFIELD_GC, [box1, box2], descr) - assert box.args == ('setfield_gc', box1, box2, descr) + box2 = BoxFloat(222.2) + fielddescr = FakeFieldDescr() + execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr) + assert cpu.fakesetfield == (box1.value, box2.value, fielddescr) # arity == 3 - box3 = BoxInt(-33) - box = execute_nonspec(cpu, rop.SETARRAYITEM_GC, [box1, box2, box3], descr) - assert box.args == ('setarrayitem_gc', box1, box2, box3, descr) + box3 = BoxInt(33) + arraydescr = FakeArrayDescr() + execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2], + arraydescr) + assert cpu.fakesetarrayitem == (box1.value, box3.value, box2.value, + arraydescr) # cases without descr # arity == 1 - box = execute_nonspec(cpu, rop.INT_INVERT, [box1]) - assert box.value == ~515 + box = execute_nonspec(cpu, None, rop.INT_INVERT, [box3]) + assert box.value == ~33 # arity == 2 - box = execute_nonspec(cpu, rop.INT_LSHIFT, [box1, BoxInt(3)]) - assert box.value == 515 << 3 + box = execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, BoxInt(3)]) + assert box.value == 33 << 3 # arity == 3 - box = execute_nonspec(cpu, rop.STRSETITEM, [box1, box2, box3]) - assert box.args == ('strsetitem', box1, box2, box3) + execute_nonspec(cpu, None, rop.STRSETITEM, [box1, BoxInt(3), box3]) + assert cpu.fakestrsetitem == (box1.value, 3, box3.value) # ints @@ -181,7 +213,7 @@ (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]), (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]), (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]), - (rop.BOOL_NOT, [(0, 1), (1, 0)]), + (rop.INT_IS_ZERO, [(0, 1), (1, 0), (2, 0), (-1, 0), (minint, 0)]), ]: for x, y in testcases: yield opnum, [x], y @@ -204,7 +236,7 @@ def test_int_ops(): cpu = FakeCPU() for opnum, boxargs, retvalue in get_int_tests(): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) assert box.getint() == retvalue # floats @@ -242,9 +274,6 @@ yield (rop.FLOAT_NEG, [15.9], 'float', -15.9) yield (rop.FLOAT_ABS, [-5.9], 'float', 5.9) yield (rop.FLOAT_ABS, [15.9], 'float', 15.9) - yield (rop.FLOAT_IS_TRUE, [-5.9], 'int', 1) - yield (rop.FLOAT_IS_TRUE, [0.0], 'int', 0) - yield (rop.FLOAT_IS_TRUE, [-0.0], 'int', 0) yield (rop.CAST_FLOAT_TO_INT, [-5.9], 'int', -5) yield (rop.CAST_FLOAT_TO_INT, [5.9], 'int', 5) yield (rop.CAST_INT_TO_FLOAT, [123], 'float', 123.0) @@ -276,7 +305,7 @@ def test_float_ops(): cpu = FakeCPU() for opnum, boxargs, rettype, retvalue in get_float_tests(cpu): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) if rettype == 'float': assert box.getfloat() == retvalue elif rettype == 'int': Modified: pypy/trunk/pypy/jit/metainterp/test/test_history.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_history.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_history.py Tue Jun 8 23:42:50 2010 @@ -9,10 +9,3 @@ s = lltype.cast_pointer(lltype.Ptr(S), t) const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)) assert const._getrepr_() == "*T" - -def test_slicing(): - h = History() - h.operations = [1, 2, 3, 4, 5] - rest = h.slice_history_at(2) - assert rest == [4, 5] - assert h.operations == [1, 2] Modified: pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py Tue Jun 8 23:42:50 2010 @@ -63,7 +63,7 @@ ] assert profiler.events == expected assert profiler.times == [2, 1, 1, 1] - assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0, + assert profiler.counters == [1, 1, 1, 1, 3, 3, 1, 7, 1, 0, 0, 0, 0, 0, 0, 0] def test_simple_loop_with_call(self): @@ -84,8 +84,8 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[1, 0], [1, 0], [0, 0]] + # calls = (executed, recorded) x (inpure, pure) + assert profiler.calls == [[1, 0], [1, 0]] def test_blackhole_pure(self): @purefunction @@ -99,12 +99,11 @@ myjitdriver.can_enter_jit(x=x, y=y, res=res, z=z) myjitdriver.jit_merge_point(x=x, y=y, res=res, z=z) res += x - if y == 1: - res += g(z) + res += g(z) y -= 1 return res * 2 res = self.meta_interp(f, [6, 7, 2]) - assert res == 90 + assert res == f(6, 7, 2) profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[0, 1], [0, 0], [0, 1]] + # calls = (executed, recorded) x (inpure, pure) + assert profiler.calls == [[0, 1], [0, 0]] Modified: pypy/trunk/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_list.py Tue Jun 8 23:42:50 2010 @@ -1,7 +1,5 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin Modified: pypy/trunk/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_loop.py Tue Jun 8 23:42:50 2010 @@ -4,7 +4,7 @@ from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import history @@ -342,7 +342,7 @@ assert res == expected def test_loop_unicode(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = u'' while n > 13: @@ -356,7 +356,7 @@ assert res == expected def test_loop_string(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = '' while n > 13: Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py Tue Jun 8 23:42:50 2010 @@ -6,7 +6,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - Const, ConstAddr, TreeLoop, BoxObj, + Const, TreeLoop, BoxObj, ConstObj, AbstractDescr) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder @@ -16,7 +16,8 @@ from pypy.jit.metainterp.specnode import VirtualArraySpecNode from pypy.jit.metainterp.specnode import VirtualStructSpecNode from pypy.jit.metainterp.specnode import ConstantSpecNode -from pypy.jit.metainterp.effectinfo import EffectInfo +from pypy.jit.codewriter.effectinfo import EffectInfo +from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int from pypy.jit.metainterp.test.oparser import parse def test_sort_descrs(): @@ -113,7 +114,7 @@ EffectInfo([adescr], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], - forces_virtual_or_virtualizable=True)) + EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)) class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though @@ -129,83 +130,81 @@ jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) - cpu.class_sizes = { - cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE), - cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2), - cpu.cast_adr_to_int(u_vtable_adr): cpu.sizeof(U), - cpu.cast_adr_to_int(jvr_vtable_adr): cpu.sizeof( - vrefinfo.JIT_VIRTUAL_REF), - } + register_known_gctype(cpu, node_vtable, NODE) + register_known_gctype(cpu, node_vtable2, NODE2) + register_known_gctype(cpu, u_vtable, U) + register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF) + namespace = locals() -class OOtypeMixin(object): +class OOtypeMixin_xxx_disabled(object): type_system = 'ootype' - def get_class_of_box(self, box): - root = box.getref(ootype.ROOT) - return ootype.classof(root) +## def get_class_of_box(self, box): +## root = box.getref(ootype.ROOT) +## return ootype.classof(root) - cpu = runner.OOtypeCPU(None) - NODE = ootype.Instance('NODE', ootype.ROOT, {}) - NODE._add_fields({'value': ootype.Signed, - 'floatval' : ootype.Float, - 'next': NODE}) - NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) - - node_vtable = ootype.runtimeClass(NODE) - node_vtable_adr = ootype.cast_to_object(node_vtable) - node_vtable2 = ootype.runtimeClass(NODE2) - node_vtable_adr2 = ootype.cast_to_object(node_vtable2) - - node = ootype.new(NODE) - nodebox = BoxObj(ootype.cast_to_object(node)) - myptr = nodebox.value - myptr2 = ootype.cast_to_object(ootype.new(NODE)) - nodebox2 = BoxObj(ootype.cast_to_object(node)) - valuedescr = cpu.fielddescrof(NODE, 'value') - floatdescr = cpu.fielddescrof(NODE, 'floatval') - nextdescr = cpu.fielddescrof(NODE, 'next') - otherdescr = cpu.fielddescrof(NODE2, 'other') - nodesize = cpu.typedescrof(NODE) - nodesize2 = cpu.typedescrof(NODE2) - - arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) - floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) - - # a plain Record - S = ootype.Record({'a': ootype.Signed, 'b': NODE}) - ssize = cpu.typedescrof(S) - adescr = cpu.fielddescrof(S, 'a') - bdescr = cpu.fielddescrof(S, 'b') - sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) - arraydescr2 = cpu.arraydescrof(ootype.Array(S)) - - T = ootype.Record({'c': ootype.Signed, - 'd': ootype.Array(NODE)}) - tsize = cpu.typedescrof(T) - cdescr = cpu.fielddescrof(T, 'c') - ddescr = cpu.fielddescrof(T, 'd') - arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) - - U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) - usize = cpu.typedescrof(U) - onedescr = cpu.fielddescrof(U, 'one') - u_vtable = ootype.runtimeClass(U) - u_vtable_adr = ootype.cast_to_object(u_vtable) - - # force a consistent order - valuedescr.sort_key() - nextdescr.sort_key() - adescr.sort_key() - bdescr.sort_key() - - FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) - nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype - - cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), - node_vtable_adr2: cpu.typedescrof(NODE2), - u_vtable_adr: cpu.typedescrof(U)} - namespace = locals() +## cpu = runner.OOtypeCPU(None) +## NODE = ootype.Instance('NODE', ootype.ROOT, {}) +## NODE._add_fields({'value': ootype.Signed, +## 'floatval' : ootype.Float, +## 'next': NODE}) +## NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) + +## node_vtable = ootype.runtimeClass(NODE) +## node_vtable_adr = ootype.cast_to_object(node_vtable) +## node_vtable2 = ootype.runtimeClass(NODE2) +## node_vtable_adr2 = ootype.cast_to_object(node_vtable2) + +## node = ootype.new(NODE) +## nodebox = BoxObj(ootype.cast_to_object(node)) +## myptr = nodebox.value +## myptr2 = ootype.cast_to_object(ootype.new(NODE)) +## nodebox2 = BoxObj(ootype.cast_to_object(node)) +## valuedescr = cpu.fielddescrof(NODE, 'value') +## floatdescr = cpu.fielddescrof(NODE, 'floatval') +## nextdescr = cpu.fielddescrof(NODE, 'next') +## otherdescr = cpu.fielddescrof(NODE2, 'other') +## nodesize = cpu.typedescrof(NODE) +## nodesize2 = cpu.typedescrof(NODE2) + +## arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) +## floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) + +## # a plain Record +## S = ootype.Record({'a': ootype.Signed, 'b': NODE}) +## ssize = cpu.typedescrof(S) +## adescr = cpu.fielddescrof(S, 'a') +## bdescr = cpu.fielddescrof(S, 'b') +## sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) +## arraydescr2 = cpu.arraydescrof(ootype.Array(S)) + +## T = ootype.Record({'c': ootype.Signed, +## 'd': ootype.Array(NODE)}) +## tsize = cpu.typedescrof(T) +## cdescr = cpu.fielddescrof(T, 'c') +## ddescr = cpu.fielddescrof(T, 'd') +## arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) + +## U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) +## usize = cpu.typedescrof(U) +## onedescr = cpu.fielddescrof(U, 'one') +## u_vtable = ootype.runtimeClass(U) +## u_vtable_adr = ootype.cast_to_object(u_vtable) + +## # force a consistent order +## valuedescr.sort_key() +## nextdescr.sort_key() +## adescr.sort_key() +## bdescr.sort_key() + +## FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) +## nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype + +## cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), +## node_vtable_adr2: cpu.typedescrof(NODE2), +## u_vtable_adr: cpu.typedescrof(U)} +## namespace = locals() class BaseTest(object): invent_fail_descr = None @@ -220,8 +219,7 @@ # def constclass(cls_vtable): if self.type_system == 'lltype': - return ConstAddr(llmemory.cast_ptr_to_adr(cls_vtable), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable))) else: return ConstObj(ootype.cast_to_object(cls_vtable)) def constant(value): @@ -357,7 +355,7 @@ assert not boxp2.fromstart assert boxp1.knownclsbox is None - assert boxp2.knownclsbox.value == self.node_vtable_adr + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr def test_find_nodes_new_2(self): ops = """ @@ -413,8 +411,8 @@ assert not boxp2.fromstart assert not boxp3.fromstart - assert boxp2.knownclsbox.value == self.node_vtable_adr - assert boxp3.knownclsbox.value == self.node_vtable_adr2 + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr + assert boxp3.knownclsbox.getaddr() == self.node_vtable_adr2 def test_find_nodes_new_aliasing_0(self): ops = """ @@ -503,31 +501,31 @@ nextdescr=Virtual(node_vtable, nextdescr=Virtual(node_vtable)))''') - def test_find_nodes_oois(self): + def test_find_nodes_ptr_eq(self): ops = """ [p3, p4, p2] p0 = new_with_vtable(ConstClass(node_vtable)) p1 = new_with_vtable(ConstClass(node_vtable)) guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -1160,14 +1158,13 @@ class TestLLtype(BaseTestOptimizeFindNode, LLtypeMixin): pass -class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): - - def test_find_nodes_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - boxes, getnode = self.find_nodes(ops, 'Not') - assert not getnode(boxes.p0).escaped +##class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): +## def test_find_nodes_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## boxes, getnode = self.find_nodes(ops, 'Not') +## assert not getnode(boxes.p0).escaped Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Tue Jun 8 23:42:50 2010 @@ -1,8 +1,7 @@ import py from pypy.rlib.objectmodel import instantiate -from pypy.jit.metainterp.test.test_resume import MyMetaInterp from pypy.jit.metainterp.test.test_optimizefindnode import (LLtypeMixin, - OOtypeMixin, + #OOtypeMixin, BaseTest) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp import optimizeopt @@ -10,18 +9,17 @@ from pypy.jit.metainterp.optimizeutil import InvalidLoop from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from pypy.jit.metainterp.jitprof import EmptyProfiler -from pypy.jit.metainterp import executor, compile, resume +from pypy.jit.metainterp import executor, compile, resume, history from pypy.jit.metainterp.resoperation import rop, opname, ResOperation from pypy.jit.metainterp.test.oparser import pure_parse -class FakeFrame(object): - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - - def __init__(self, code="", pc=0, exc_target=-1): - self.jitcode = code - self.pc = pc - self.exception_target = exc_target +##class FakeFrame(object): +## parent_resumedata_snapshot = None +## parent_resumedata_frame_info_list = None + +## def __init__(self, code="", pc=0): +## self.jitcode = code +## self.pc = pc class Fake(object): failargs_limit = 1000 @@ -45,9 +43,8 @@ fdescr = ResumeGuardDescr(None, None) op = ResOperation(rop.GUARD_TRUE, [], None, descr=fdescr) # setup rd data - fi0 = resume.FrameInfo(None, FakeFrame("code0", 1, 2)) - fdescr.rd_frame_info_list = resume.FrameInfo(fi0, - FakeFrame("code1", 3, -1)) + fi0 = resume.FrameInfo(None, "code0", 11) + fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) snapshot0 = resume.Snapshot(None, [b0]) fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1]) # @@ -215,14 +212,18 @@ def __eq__(self, other): return type(self) is type(other) # xxx obscure +def _sortboxes(boxes): + _kind2count = {history.INT: 1, history.REF: 2, history.FLOAT: 3} + return sorted(boxes, key=lambda box: _kind2count[box.type]) + class BaseTestOptimizeOpt(BaseTest): def invent_fail_descr(self, fail_args): if fail_args is None: return None descr = Storage() - descr.rd_frame_info_list = resume.FrameInfo(None, FakeFrame()) - descr.rd_snapshot = resume.Snapshot(None, fail_args) + descr.rd_frame_info_list = resume.FrameInfo(None, "code", 11) + descr.rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args)) return descr def assert_equal(self, optimized, expected): @@ -273,7 +274,7 @@ i0 = int_add(2, 3) i1 = int_is_true(i0) guard_true(i1) [] - i2 = bool_not(i1) + i2 = int_is_zero(i1) guard_false(i2) [] guard_value(i0, 5) [] jump() @@ -289,7 +290,7 @@ from pypy.jit.metainterp.executor import execute_nonspec from pypy.jit.metainterp.history import BoxInt import random - for opnum in range(rop.INT_ADD, rop.BOOL_NOT+1): + for opnum in range(rop.INT_ADD, rop.SAME_AS+1): try: op = opname[opnum] except KeyError: @@ -309,7 +310,7 @@ jump() """ % (op.lower(), ', '.join(map(str, args))) argboxes = [BoxInt(a) for a in args] - expected_value = execute_nonspec(self.cpu, opnum, + expected_value = execute_nonspec(self.cpu, None, opnum, argboxes).getint() expected = """ [] @@ -410,7 +411,7 @@ self.optimize_loop(ops, 'Not', expected) def test_int_is_true_1(self): - py.test.skip("too bad") + py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -427,6 +428,24 @@ """ self.optimize_loop(ops, 'Not', expected) + def test_int_is_true_is_zero(self): + py.test.skip("XXX implement me") + ops = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + expected = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + self.optimize_loop(ops, 'Not', expected) + def test_ooisnull_oononnull_2(self): ops = """ [p0] @@ -478,13 +497,13 @@ ops = """ [p0] guard_class(p0, ConstClass(node_vtable)) [] - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] jump(p0) """ @@ -499,13 +518,13 @@ ops = """ [p0] setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] guard_nonnull(p0) [] jump(p0) @@ -728,25 +747,25 @@ ops = """ [p0, p1, p2] guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -766,17 +785,17 @@ expected2 = """ [p0, p1, p2] guard_nonnull(p0) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -870,7 +889,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, NULL, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -886,7 +905,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, ConstPtr(myptr), descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -1514,7 +1533,7 @@ """ expected = """ [p1, i2, i3] - guard_true(i3) [p1, i2] + guard_true(i3) [i2, p1] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) @@ -1920,7 +1939,7 @@ ops = """ [p1] guard_class(p1, ConstClass(node_vtable2)) [] - i = ooisnot(ConstPtr(myptr), p1) + i = ptr_ne(ConstPtr(myptr), p1) guard_true(i) [] jump(p1) """ @@ -1936,9 +1955,9 @@ [p0] p1 = getfield_gc(p0, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) guard_true(i1) [] - i2 = ooisnot(p1, p2) + i2 = ptr_ne(p1, p2) guard_false(i2) [] jump(p0) """ @@ -1952,8 +1971,8 @@ def test_remove_duplicate_pure_op(self): ops = """ [p1, p2] - i1 = oois(p1, p2) - i2 = oois(p1, p2) + i1 = ptr_eq(p1, p2) + i2 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -1968,7 +1987,7 @@ """ expected = """ [p1, p2] - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -2024,7 +2043,7 @@ # typically called twice, before and after optimization if self.oparse is None: fdescr.rd_frame_info_list = resume.FrameInfo(None, - FakeFrame()) + "code", 11) fdescr.rd_snapshot = resume.Snapshot(None, fail_args) self.oparse = oparse # @@ -2096,7 +2115,7 @@ for pvar, pfieldname, pfieldvar in pendingfields: box = oparse.getvar(pvar) fielddescr = self.namespace[pfieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, box) @@ -2114,13 +2133,13 @@ if tag[0] in ('virtual', 'vstruct'): fieldname, fieldvalue = fieldtext.split('=') fielddescr = self.namespace[fieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, resolved) elif tag[0] == 'varray': fieldvalue = fieldtext - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETARRAYITEM_GC, tag[1], resolved, ConstInt(index)) @@ -2130,12 +2149,14 @@ index += 1 def check_expanded_fail_descr(self, expectedtext, guard_opnum): + from pypy.jit.metainterp.test.test_resume import ResumeDataFakeReader + from pypy.jit.metainterp.test.test_resume import MyMetaInterp guard_op, = [op for op in self.loop.operations if op.is_guard()] fail_args = guard_op.fail_args fdescr = guard_op.descr assert fdescr.guard_opnum == guard_opnum - reader = resume.ResumeDataReader(fdescr, fail_args, - MyMetaInterp(self.cpu)) + reader = ResumeDataFakeReader(fdescr, fail_args, + MyMetaInterp(self.cpu)) boxes = reader.consume_boxes() self._verify_fail_args(boxes, fdescr.oparse, expectedtext) @@ -2190,7 +2211,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p3, descr=nextdescr) - guard_true(i1, descr=fdescr) [p1, i3] + guard_true(i1, descr=fdescr) [i3, p1] jump(i2, i1, i3, p3) """ expected = """ @@ -2199,15 +2220,14 @@ jump(i2, 1, i3, p3) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3 + self.check_expanded_fail_descr('''i3, p1 where p1 is a node_vtable, valuedescr=1, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p3 ''', rop.GUARD_TRUE) def test_expand_fail_4(self): - for arg in ['p1', 'p1,i2', 'i2,p1', 'p1,p2', 'p2,p1', - 'p1,p2,i2', 'p1,i2,p2', 'p2,p1,i2', - 'p2,i2,p1', 'i2,p1,p2', 'i2,p2,p1']: + for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1', + 'i2,p1,p2', 'i2,p2,p1']: self.make_fail_descr() ops = """ [i1, i2, i3] @@ -2218,7 +2238,7 @@ setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) - guard_true(i1, descr=fdescr) [i4, %s, i3] + guard_true(i1, descr=fdescr) [i4, i3, %s] jump(i1, i2, i3) """ expected = """ @@ -2227,7 +2247,7 @@ jump(1, i2, i3) """ self.optimize_loop(ops % arg, 'Not, Not, Not', expected) - self.check_expanded_fail_descr('''i3, %s, i3 + self.check_expanded_fail_descr('''i3, i3, %s where p1 is a node_vtable, valuedescr=i2, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2''' % arg, rop.GUARD_TRUE) @@ -2242,7 +2262,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p1, descr=nextdescr) # a cycle - guard_true(i1, descr=fdescr) [p1, i3, p2, i4] + guard_true(i1, descr=fdescr) [i3, i4, p1, p2] jump(i2, i1, i3, i4) """ expected = """ @@ -2251,7 +2271,7 @@ jump(i2, 1, i3, i4) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3, p2, i4 + self.check_expanded_fail_descr('''i3, i4, p1, p2 where p1 is a node_vtable, valuedescr=i4, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p1 ''', rop.GUARD_TRUE) @@ -2627,7 +2647,7 @@ setfield_gc(p2, 5, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p1) """ # XXX we should optimize a bit more the case of a nonvirtual. @@ -2669,7 +2689,7 @@ setfield_gc(p1b, 252, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ self.optimize_loop(ops, 'Not, Not', expected) @@ -2710,7 +2730,7 @@ setfield_gc(p1b, i1, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ # the point of this test is that 'i1' should show up in the fail_args @@ -2781,7 +2801,7 @@ escape(p2) p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [] jump(i1) @@ -2807,7 +2827,7 @@ setfield_gc(p2, 23, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [i1] jump(i1, p1) @@ -2881,31 +2901,31 @@ ''' self.optimize_loop(ops, 'Not', expected) -class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): +##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): - def test_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - expected = """ - [i0] - jump(1) - """ - self.optimize_loop(ops, 'Not', expected) +## def test_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## expected = """ +## [i0] +## jump(1) +## """ +## self.optimize_loop(ops, 'Not', expected) - def test_instanceof_guard_class(self): - ops = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - i1 = instanceof(p0, descr=nodesize) - jump(i1, p0) - """ - expected = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - jump(1, p0) - """ - self.optimize_loop(ops, 'Not, Not', expected) +## def test_instanceof_guard_class(self): +## ops = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## i1 = instanceof(p0, descr=nodesize) +## jump(i1, p0) +## """ +## expected = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## jump(1, p0) +## """ +## self.optimize_loop(ops, 'Not, Not', expected) Modified: pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py Tue Jun 8 23:42:50 2010 @@ -1,49 +1,20 @@ # some unit tests for the bytecode decoding -from pypy.jit.metainterp import pyjitpl, codewriter, resoperation, history +from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp import jitprof -from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.history import History from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.test.test_optimizeopt import equaloplists +from pypy.jit.codewriter.jitcode import JitCode -def make_frame(code): - bytecode = codewriter.JitCode("hello") - bytecode.code = code - bytecode.constants = None - frame = pyjitpl.MIFrame(None, bytecode) - frame.pc = 0 - return frame - - -def test_decode_big_int(): - for code, value in [("\x80\x01", 128), ("\x81\x81\x01", 1 + (1 << 7) + (1 << 14))]: - frame = make_frame(code) - val = frame.load_int() - assert val == value - -def test_decode_bool(): - frame = make_frame("\x00") - assert not frame.load_bool() - - frame = make_frame("\x01") - assert frame.load_bool() - -def test_simple_opimpl_exist(): - rop = resoperation.rop - for opnum, opname in resoperation.opname.items(): - if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE, - rop.FORCE_TOKEN): - continue - if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST: - assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname def test_portal_trace_positions(): - jitcode = codewriter.JitCode("f") - jitcode.code = jitcode.constants = None - portal = codewriter.JitCode("portal") - portal.code = portal.constants = None + jitcode = JitCode("f") + jitcode.setup(None) + portal = JitCode("portal") + portal.setup(None) class FakeStaticData: cpu = None portal_code = portal @@ -95,7 +66,7 @@ c3 = ConstInt(3) boxes = [b1, b2, b1, c3] dup = {} - metainterp.remove_consts_and_duplicates(boxes, 0, 4, dup) + metainterp.remove_consts_and_duplicates(boxes, 4, dup) assert boxes[0] is b1 assert boxes[1] is b2 assert is_another_box_like(boxes[2], b1) @@ -108,12 +79,12 @@ # del metainterp.history.operations[:] b4 = BoxInt(4) - boxes = ["something random", b2, b4, "something else"] - metainterp.remove_consts_and_duplicates(boxes, 1, 3, dup) - assert is_another_box_like(boxes[1], b2) - assert boxes[2] is b4 + boxes = [b2, b4, "something random"] + metainterp.remove_consts_and_duplicates(boxes, 2, dup) + assert is_another_box_like(boxes[0], b2) + assert boxes[1] is b4 assert equaloplists(metainterp.history.operations, [ - ResOperation(rop.SAME_AS, [b2], boxes[1]), + ResOperation(rop.SAME_AS, [b2], boxes[0]), ]) def test_get_name_from_address(): @@ -121,42 +92,7 @@ def __init__(self): pass metainterp_sd = FakeMetaInterpSd() - metainterp_sd.info_from_codewriter(None, None, - [(123, "a"), (456, "b")], - None) + metainterp_sd.setup_list_of_addr2name([(123, 'a'), (456, 'b')]) assert metainterp_sd.get_name_from_address(123) == 'a' assert metainterp_sd.get_name_from_address(456) == 'b' assert metainterp_sd.get_name_from_address(789) == '' - -def test_initialize_state_from_guard_failure(): - from pypy.jit.metainterp.typesystem import llhelper - calls = [] - - class FakeCPU: - ts = llhelper - - def make_boxes_from_latest_values(self, faildescr): - return [BoxInt(0), None, BoxInt(2), None, BoxInt(4)] - - class FakeStaticData: - cpu = FakeCPU() - profiler = jitprof.EmptyProfiler() - - metainterp = pyjitpl.MetaInterp(FakeStaticData()) - - def rebuild_state_after_failure(descr, newboxes): - calls.append(newboxes) - metainterp.rebuild_state_after_failure = rebuild_state_after_failure - - class FakeResumeDescr: - def must_compile(self, *args): - return True - resumedescr = FakeResumeDescr() - metainterp.initialize_state_from_guard_failure(resumedescr) - - inp = metainterp.history.inputargs - assert len(inp) == 3 - assert [box.value for box in inp] == [0, 2, 4] - b0, b2, b4 = inp - assert len(calls) == 1 - assert calls[0] == [b0, None, b2, None, b4] Modified: pypy/trunk/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_recursive.py Tue Jun 8 23:42:50 2010 @@ -1,7 +1,8 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint +from pypy.rlib.jit import unroll_safe from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats @@ -24,6 +25,7 @@ return 1 res = self.meta_interp(main, [20], optimizer=OPTIMIZER_SIMPLE) assert res == main(20) + self.check_history(call=0) def test_simple_recursion_with_exc(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm']) @@ -105,11 +107,11 @@ def can_inline(*args): return True else: - def can_inline(code, i): + def can_inline(i, code): code = hlstr(code) return not JUMP_BACK in code - jitdriver = JitDriver(greens = ['code', 'i'], reds = ['n'], + jitdriver = JitDriver(greens = ['i', 'code'], reds = ['n'], can_inline = can_inline) def interpret(codenum, n, i): @@ -178,12 +180,12 @@ def test_guard_failure_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -215,12 +217,12 @@ def test_guard_failure_and_then_exception_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n', 'flag'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n', 'flag'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -259,12 +261,12 @@ def test_exception_in_inlined_function(self): from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) class Exc(Exception): @@ -305,12 +307,12 @@ # it fails, it is very delicate in terms of parameters, # bridge/loop creation order from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -394,9 +396,36 @@ self.check_aborted_count(8) self.check_enter_count_at_most(30) + def test_trace_limit_with_exception_bug(self): + myjitdriver = JitDriver(greens=[], reds=['n']) + @unroll_safe + def do_stuff(n): + while n > 0: + n -= 1 + raise ValueError + def loop(n): + pc = 0 + while n > 80: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + try: + do_stuff(n) + except ValueError: + # the trace limit is checked when we arrive here, and we + # have the exception still in last_exc_value_box at this + # point -- so when we abort because of a trace too long, + # the exception is passed to the blackhole interp and + # incorrectly re-raised from here + pass + n -= 1 + return n + TRACE_LIMIT = 66 + res = self.meta_interp(loop, [100], trace_limit=TRACE_LIMIT) + assert res == 80 + def test_max_failure_args(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -429,7 +458,7 @@ def test_max_failure_args_exc(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -495,12 +524,12 @@ self.check_loops(call_may_force=0, call=0) def test_trace_from_start(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -535,12 +564,12 @@ self.check_history(int_add=1) def test_dont_inline_huge_stuff(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -693,7 +722,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -729,7 +758,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -770,7 +799,7 @@ assert res == main(0) def test_directly_call_assembler_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'x', 'frame'], virtualizables = ['frame'], can_inline = lambda codeno : False) @@ -816,7 +845,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) Modified: pypy/trunk/pypy/jit/metainterp/test/test_resume.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_resume.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_resume.py Tue Jun 8 23:42:50 2010 @@ -3,10 +3,11 @@ from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue from pypy.jit.metainterp.optimizeopt import VStructValue from pypy.jit.metainterp.resume import * -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, ConstAddr +from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.history import ConstPtr, ConstFloat from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin from pypy.jit.metainterp import executor +from pypy.jit.codewriter import heaptracker class Storage: rd_frame_info_list = None @@ -60,12 +61,12 @@ self.resboxes = [] def newframe(self, jitcode): - frame = FakeFrame(jitcode, -1, -1) + frame = FakeFrame(jitcode, -1) self.framestack.append(frame) return frame def execute_and_record(self, opnum, descr, *argboxes): - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) + resbox = executor.execute(self.cpu, None, opnum, descr, *argboxes) self.trace.append((opnum, list(argboxes), resbox, @@ -74,10 +75,75 @@ self.resboxes.append(resbox) return resbox +S = lltype.GcStruct('S') +gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcrefnull = lltype.nullptr(llmemory.GCREF.TO) + +class MyCPU: + class ts: + NULLREF = gcrefnull + CONST_NULL = ConstPtr(gcrefnull) + def __init__(self, values): + self.values = values + def get_latest_value_count(self): + return len(self.values) + def get_latest_value_int(self, index): + return self.values[index] + def get_latest_value_ref(self, index): + return self.values[index] + def get_latest_value_float(self, index): + return self.values[index] + +class MyBlackholeInterp: + def __init__(self, ARGS): + self.written_i = [] + self.written_r = [] + self.written_f = [] + self.ARGS = ARGS + + def get_current_position_info(self): + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + count_i = count_r = count_f = 0 + for index, ARG in enumerate(self.ARGS): + if ARG == lltype.Signed: + callback_i(index, count_i); count_i += 1 + elif ARG == llmemory.GCREF: + callback_r(index, count_r); count_r += 1 + elif ARG == lltype.Float: + callback_f(index, count_f); count_f += 1 + else: + assert 0 + return MyInfo() + + def setarg_i(self, index, value): + assert index == len(self.written_i) + self.written_i.append(value) + + def setarg_r(self, index, value): + assert index == len(self.written_r) + self.written_r.append(value) + + def setarg_f(self, index, value): + assert index == len(self.written_f) + self.written_f.append(value) + +def _next_section(reader, *expected): + bh = MyBlackholeInterp(map(lltype.typeOf, expected)) + reader.consume_one_section(bh) + expected_i = [x for x in expected if lltype.typeOf(x) == lltype.Signed] + expected_r = [x for x in expected if lltype.typeOf(x) == llmemory.GCREF] + expected_f = [x for x in expected if lltype.typeOf(x) == lltype.Float] + assert bh.written_i == expected_i + assert bh.written_r == expected_r + assert bh.written_f == expected_f + def test_simple_read(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] - c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] + #b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] + c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)] storage = Storage() storage.rd_consts = [c1, c2, c3] numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) @@ -88,44 +154,54 @@ tag(0, TAGBOX), tag(1, TAGBOX)]) storage.rd_numb = numb - - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), LLtypeMixin.cpu.ts.CONST_NULL, b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([42, gcref1, -66]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 42, 111, gcrefnull, 42, gcref1) + _next_section(reader, 222, 333) + _next_section(reader, 42, gcref1, -66) + # + metainterp = MyMetaInterp(cpu) + reader = ResumeDataBoxReader(storage, metainterp) + bi, br, bf = [None]*3, [None]*2, [None]*0 + info = MyBlackholeInterp([lltype.Signed, lltype.Signed, + llmemory.GCREF, lltype.Signed, + llmemory.GCREF]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b1s = reader.liveboxes[0] + b2s = reader.liveboxes[1] + assert bi == [b1s, ConstInt(111), b1s] + assert br == [ConstPtr(gcrefnull), b2s] + bi, br, bf = [None]*2, [None]*0, [None]*0 + info = MyBlackholeInterp([lltype.Signed, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + assert bi == [ConstInt(222), ConstInt(333)] + bi, br, bf = [None]*2, [None]*1, [None]*0 + info = MyBlackholeInterp([lltype.Signed, llmemory.GCREF, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b3s = reader.liveboxes[2] + assert bi == [b1s, b3s] + assert br == [b2s] + # def test_simple_read_tagged_ints(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] storage = Storage() storage.rd_consts = [] - numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) - numb = Numbering(numb, [tag(2, TAGINT), tag(3, TAGINT)]) - numb = Numbering(numb, [tag(0, TAGBOX), - tag(1, TAGINT), - tag(0, TAGBOX), - tag(1, TAGBOX)]) + numb = Numbering(None, [tag(100, TAGINT)]) storage.rd_numb = numb - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 100) def test_prepare_virtuals(): class FakeVinfo(object): - def allocate(self, metainterp): + def allocate(self, decoder): return "allocated" - def setfields(self, metainterp, virtual, func): + def setfields(self, decoder, virtual): assert virtual == "allocated" class FakeStorage(object): rd_virtuals = [FakeVinfo(), None] @@ -135,8 +211,8 @@ class FakeMetainterp(object): _already_allocated_resume_virtuals = None cpu = None - reader = ResumeDataReader(FakeStorage(), [], FakeMetainterp()) - assert reader.virtuals == ["allocated", None] + reader = ResumeDataDirectReader(None, FakeStorage()) + assert reader.virtuals == ["allocated", reader.virtual_default] # ____________________________________________________________ @@ -146,11 +222,13 @@ parent_resumedata_snapshot = None parent_resumedata_frame_info_list = None - def __init__(self, code, pc, exc_target, *boxes): + def __init__(self, code, pc, *boxes): self.jitcode = code self.pc = pc - self.exception_target = exc_target - self.env = list(boxes) + self._env = list(boxes) + + def get_list_of_active_boxes(self, flag): + return self._env def setup_resume_at_op(self, pc, exception_target, env): self.__init__(self.jitcode, pc, exception_target, *env) @@ -160,8 +238,7 @@ def __ne__(self, other): return self.__dict__ != other.__dict__ def __repr__(self): - return "" % (self.jitcode, self.pc, - self.exception_target, self.env) + return "" % (self.jitcode, self.pc, self._env) def test_Snapshot_create(): l = ['b0', 'b1'] @@ -176,20 +253,16 @@ def test_FrameInfo_create(): jitcode = "JITCODE" - frame = FakeFrame(jitcode, 1, 2) - fi = FrameInfo(None, frame) + fi = FrameInfo(None, jitcode, 1) assert fi.prev is None assert fi.jitcode is jitcode assert fi.pc == 1 - assert fi.exception_target == 2 jitcode1 = "JITCODE1" - frame1 = FakeFrame(jitcode, 3, 4) - fi1 = FrameInfo(fi, frame1) + fi1 = FrameInfo(fi, jitcode1, 3) assert fi1.prev is fi - assert fi1.jitcode is jitcode + assert fi1.jitcode is jitcode1 assert fi1.pc == 3 - assert fi1.exception_target == 4 def test_Numbering_create(): l = [1, 2] @@ -205,7 +278,7 @@ def test_capture_resumedata(): b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] - fs = [FakeFrame("code0", 0, -1, b1, c1, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2)] storage = Storage() capture_resumedata(fs, None, [], storage) @@ -218,13 +291,12 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) frame_info_list = storage.rd_frame_info_list @@ -235,26 +307,23 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env - assert snapshot.boxes is not fs[2].env + assert snapshot.boxes == fs[2]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is fs[1].parent_resumedata_frame_info_list assert frame_info_list.jitcode == 'code1' snapshot = snapshot.prev assert snapshot.prev is fs[1].parent_resumedata_snapshot - assert snapshot.boxes == fs[1].env - assert snapshot.boxes is not fs[1].env + assert snapshot.boxes == fs[1]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is None assert frame_info_list.jitcode == 'code0' snapshot = snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env - fs[2].env = [b2, b3] + fs[2]._env = [b3, b2] fs[2].pc = 15 vbs = [b1, b2] vrs = [b3] @@ -266,16 +335,11 @@ assert frame_info_list.pc == 15 snapshot = storage.rd_snapshot - assert snapshot.boxes == vbs - assert snapshot.boxes is not vbs - - snapshot = snapshot.prev - assert snapshot.boxes == vrs - assert snapshot.boxes is not vrs + assert snapshot.boxes == vrs + vbs # in the same list snapshot = snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env + assert snapshot.boxes == fs[2]._env class FakeMetaInterpStaticData: @@ -285,12 +349,13 @@ failargs_limit = 100 def test_rebuild_from_resumedata(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -300,21 +365,21 @@ b1t, b2t, b3t = [BoxInt(), BoxPtr(), BoxInt()] newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t) - result = rebuild_from_resumedata(metainterp, newboxes, storage, - False) + result = rebuild_from_resumedata(metainterp, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_with_virtualizable(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxPtr()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, [b4], [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -327,21 +392,22 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, True) assert result == ([b4t], []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -359,9 +425,9 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b2, b3, b4], b1t, b2t, b3t, b4t) @@ -370,7 +436,7 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage2, False) assert result == (None, []) - fs2 = fs2[:-1] + [FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = fs2[:-1] + [FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 @@ -379,6 +445,9 @@ pass fakeoptimizer = FakeOptimizer_VirtualValue() +def ConstAddr(addr, cpu): # compatibility + return ConstInt(heaptracker.adr2int(addr)) + def virtual_value(keybox, value, next): vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu), keybox) @@ -389,17 +458,18 @@ return vv def test_rebuild_from_resumedata_two_guards_w_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -433,9 +503,9 @@ False) b2t = metainterp.resboxes[0] - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b3, b4], b1t, b3t, b4t) @@ -445,17 +515,18 @@ False) b2t = metainterp.resboxes[0] assert len(metainterp.resboxes) == 2 - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards_w_shared_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5, b6 = [BoxPtr(), BoxPtr(), BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, c1, b2, b3)] + fs = [FakeFrame("code0", 0, c1, b2, b3)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -467,7 +538,7 @@ tag(0, TAGCONST)] storage2 = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b4, b2)] + fs = [FakeFrame("code0", 0, b1, b4, b2)] capture_resumedata(fs, None, [], storage2) values[b4] = virtual_value(b4, b6, c4) modifier = ResumeDataVirtualAdder(storage2, memo) @@ -478,9 +549,10 @@ def test_resumedata_top_recursive_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxPtr(), BoxPtr(), BoxInt()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b2)] + fs = [FakeFrame("code0", 0, b1, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -727,16 +799,11 @@ modifier = ResumeDataVirtualAdder(storage, memo) liveboxes = modifier.finish({}) assert storage.rd_snapshot is None - metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, [], metainterp) - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [ConstInt(sys.maxint), ConstInt(1), ConstInt(sys.maxint), - ConstInt(2**16)] - assert metainterp.trace == [] + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, sys.maxint, 2**16, -65) + _next_section(reader, 2, 3) + _next_section(reader, sys.maxint, 1, sys.maxint, 2**16) def test_virtual_adder_memo_const_sharing(): @@ -756,6 +823,46 @@ assert storage2.rd_consts is memo.consts +class ResumeDataFakeReader(ResumeDataBoxReader): + """Another subclass of AbstractResumeDataReader meant for tests.""" + def __init__(self, storage, newboxes, metainterp): + self._init(metainterp.cpu, storage) + self.liveboxes = newboxes + self.metainterp = metainterp + self._prepare(storage) + + def consume_boxes(self): + self.lst = [] + class Whatever: + def __eq__(self, other): + return True + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + for index, tagged in enumerate(self.cur_numb.nums): + box = self.decode_box(tagged, Whatever()) + if box.type == INT: + callback_i(index, index) + elif box.type == REF: + callback_r(index, index) + elif box.type == FLOAT: + callback_f(index, index) + else: + assert 0 + self._prepare_next_section(MyInfo()) + return self.lst + + def write_an_int(self, count_i, box): + assert box.type == INT + self.lst.append(box) + def write_a_ref(self, count_r, box): + assert box.type == REF + self.lst.append(box) + def write_a_float(self, count_f, box): + assert box.type == FLOAT + self.lst.append(box) + + def test_virtual_adder_no_op_renaming(): b1s, b2s, b3s = [BoxInt(1), BoxInt(2), BoxInt(3)] storage = make_storage(b1s, b2s, b3s) @@ -777,7 +884,7 @@ b1t, b3t = [BoxInt(11), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b1_2, b3s], b1t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() assert lst == [b1t, b1t, b3t] lst = reader.consume_boxes() @@ -797,7 +904,7 @@ b2t, b3t = [BoxPtr(demo55o), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() c1t = ConstInt(111) assert lst == [c1t, b2t, b3t] @@ -849,10 +956,10 @@ b5s], b3t, b5t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 2 - b2t = reader._decode_box(modifier._gettagged(b2s)) - b4t = reader._decode_box(modifier._gettagged(b4s)) + b2t = reader.decode_ref(modifier._gettagged(b2s)) + b4t = reader.decode_ref(modifier._gettagged(b4s)) trace = metainterp.trace b2new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu)], @@ -912,9 +1019,9 @@ b4t) # resume metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ (rop.NEW_ARRAY, [ConstInt(2)], b2t, LLtypeMixin.arraydescr), @@ -957,9 +1064,9 @@ # NULL = ConstPtr.value metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ @@ -1004,7 +1111,7 @@ newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert reader.virtuals is None trace = metainterp.trace b2set = (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr) Modified: pypy/trunk/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_send.py Tue Jun 8 23:42:50 2010 @@ -1,7 +1,6 @@ import py from pypy.rlib.jit import JitDriver, hint, purefunction -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -375,7 +374,7 @@ self.check_loop_count(2) def test_behavior_change_after_a_while(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x']) class Base: def __init__(self, value): self.value = value @@ -455,7 +454,7 @@ self.check_tree_loop_count(2) def test_bug1(self): - myjitdriver = JitDriver(greens = [], reds = ['node', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) class Base: pass class A(Base): Modified: pypy/trunk/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_slist.py Tue Jun 8 23:42:50 2010 @@ -1,5 +1,4 @@ import py -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE @@ -65,7 +64,7 @@ assert res == 0 def test_getitem(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'lst', 'i']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'lst']) def f(n): lst = [] for i in range(n): Modified: pypy/trunk/pypy/jit/metainterp/test/test_string.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_string.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_string.py Tue Jun 8 23:42:50 2010 @@ -1,13 +1,13 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class StringTests: def test_eq_residual(self): - jitdriver = JitDriver(greens = [], reds = ['s', 'n', 'i']) + jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's']) global_s = "hello" def f(n, b, s): if b: @@ -44,6 +44,34 @@ assert res == 5 self.check_loops(**{self.CALL_PURE: 0}) + def test_newstr(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = 'adlfkj' + chr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + + def test_newunicode(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = u'adlfkj' + unichr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + class TestOOtype(StringTests, OOJitMixin): CALL_PURE = "oosend_pure" Modified: pypy/trunk/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_tl.py Tue Jun 8 23:42:50 2010 @@ -1,6 +1,6 @@ import py -from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import OPTIMIZER_SIMPLE +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin Modified: pypy/trunk/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_tlc.py Tue Jun 8 23:42:50 2010 @@ -21,7 +21,7 @@ pool = tlc.ConstantPool() bytecode = tlc.compile(src, pool) interp = self._get_interp(bytecode, pool) - return self.meta_interp(interp, [0, inputarg], view=False) + return self.meta_interp(interp, [0, inputarg]) def test_method(self): code = """ Modified: pypy/trunk/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_virtual.py Tue Jun 8 23:42:50 2010 @@ -1,12 +1,12 @@ import py from pypy.rlib.jit import JitDriver, hint from pypy.rlib.objectmodel import compute_unique_id -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.ootypesystem import ootype -from pypy.jit.metainterp import heaptracker +from pypy.jit.codewriter import heaptracker class VirtualTests: def _freeze_(self): @@ -299,10 +299,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) class VirtualMiscTests: Modified: pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py Tue Jun 8 23:42:50 2010 @@ -2,14 +2,15 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy +from pypy.jit.codewriter import heaptracker from pypy.rlib.jit import JitDriver, hint, dont_look_inside from pypy.rlib.jit import OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.rarithmetic import intmask from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.rclass import FieldListAccessor from pypy.jit.metainterp.warmspot import get_stats, get_translator -from pypy.jit.metainterp import history, heaptracker +from pypy.jit.metainterp import history from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin def promote_virtualizable(*args): @@ -461,7 +462,7 @@ def test_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -521,7 +522,7 @@ def test_external_pass(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 'z'], + jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'], virtualizables = ['frame']) class BaseFrame(object): @@ -583,6 +584,45 @@ self.check_aborted_count(2) self.check_tree_loop_count(0) + def test_external_read_with_exception(self): + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = ['x', 'y'] + class SomewhereElse: + pass + somewhere_else = SomewhereElse() + + class FooError(Exception): + def __init__(self, value): + self.value = value + + def g(): + result = somewhere_else.top_frame.y # external read + debug_print(lltype.Void, '-+-+-+-+- external read:', result) + raise FooError(result) + + def f(n): + frame = Frame() + frame.x = n + frame.y = 10 + somewhere_else.top_frame = frame + while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) + try: + g() + except FooError, e: + frame.x -= e.value + frame.y += 1 + return frame.x + + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) + assert res == f(123) + self.check_aborted_count(2) + self.check_tree_loop_count(0) + def test_external_write(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -821,7 +861,7 @@ assert res == f(123) def test_external_read_sometimes_recursive(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'rec'], + jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -941,7 +981,7 @@ assert res == f(123) def test_promote_index_in_virtualizable_list(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1084,7 +1124,7 @@ res = self.meta_interp(f, [10]) assert res == 55 - self.check_loops(new_with_vtable=0, oois=1) + self.check_loops(new_with_vtable=0, ptr_eq=1) def test_virtual_child_frame_with_arrays(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], @@ -1196,7 +1236,7 @@ if not self.basic: py.test.skip("purely frontend test") - myjitdriver = JitDriver(greens = [], reds = ['frame', 'fail'], + myjitdriver = JitDriver(greens = [], reds = ['fail', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -1251,7 +1291,7 @@ self.x = x self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) def interp(caller): @@ -1284,15 +1324,15 @@ self.n = n self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['frame'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['frame'], virtualizables=["frame"], get_printable_location=p, can_inline=c) def f(code, frame): Modified: pypy/trunk/pypy/jit/metainterp/test/test_virtualref.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_virtualref.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_virtualref.py Tue Jun 8 23:42:50 2010 @@ -12,9 +12,9 @@ class VRefTests: - def finish_metainterp_for_interp_operations(self, metainterp): - self.vrefinfo = VirtualRefInfo(metainterp.staticdata.state) - metainterp.staticdata.virtualref_info = self.vrefinfo + def finish_setup_for_interp_operations(self): + self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) + self.cw.setup_vrefinfo(self.vrefinfo) def test_make_vref_simple(self): class X: @@ -81,8 +81,26 @@ JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # - self.metainterp.rebuild_state_after_failure(guard_op.descr, - guard_op.fail_args[:]) + # try reloading from blackhole.py's point of view + from pypy.jit.metainterp.resume import ResumeDataDirectReader + cpu = self.metainterp.cpu + cpu.get_latest_value_count = lambda : len(guard_op.fail_args) + cpu.get_latest_value_int = lambda i:guard_op.fail_args[i].getint() + cpu.get_latest_value_ref = lambda i:guard_op.fail_args[i].getref_base() + cpu.clear_latest_values = lambda count: None + resumereader = ResumeDataDirectReader(cpu, guard_op.descr) + vrefinfo = self.metainterp.staticdata.virtualref_info + lst = [] + vrefinfo.continue_tracing = lambda vref, virtual: \ + lst.append((vref, virtual)) + resumereader.consume_vref_and_vable(vrefinfo, None) + del vrefinfo.continue_tracing + assert len(lst) == 1 + lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), + lst[0][0]) # assert correct type + # + # try reloading from pyjitpl's point of view + self.metainterp.rebuild_state_after_failure(guard_op.descr) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value @@ -424,7 +442,7 @@ self.check_aborted_count(0) def test_recursive_call_1(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: pass @@ -454,7 +472,7 @@ self.check_aborted_count(0) def test_recursive_call_2(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: n = 0 Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py Tue Jun 8 23:42:50 2010 @@ -277,13 +277,13 @@ type_system = 'lltype' class TestOOWarmspot(WarmspotTests, OOJitMixin): - CPUClass = runner.OOtypeCPU + ##CPUClass = runner.OOtypeCPU type_system = 'ootype' class TestWarmspotDirect(object): def setup_class(cls): from pypy.jit.metainterp.typesystem import llhelper - from pypy.jit.metainterp.support import annotate + from pypy.jit.codewriter.support import annotate from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.rpython.lltypesystem import lltype, llmemory @@ -299,7 +299,7 @@ raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally( - [BoxInt(0), BoxInt(1)]) + [0], [], [], [1], [], []) if self.no == 3: exc = lltype.malloc(OBJECT) exc.typeptr = exc_vtable @@ -308,10 +308,15 @@ lltype.cast_opaque_ptr(llmemory.GCREF, exc)) return self.no + class FakeDescr: + def as_vtable_size_descr(self): + return self + class FakeCPU(object): supports_floats = False ts = llhelper translate_support_code = False + stats = "stats" def get_fail_descr_number(self, d): return -1 @@ -320,7 +325,7 @@ pass def nodescr(self, *args, **kwds): - pass + return FakeDescr() fielddescrof = nodescr calldescrof = nodescr sizeof = nodescr @@ -343,6 +348,7 @@ return red rtyper = annotate(f, [0]) + FakeCPU.rtyper = rtyper translator = rtyper.annotator.translator translator.config.translation.gc = 'hybrid' cls.desc = WarmRunnerDesc(translator, CPUClass=FakeCPU) Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py Tue Jun 8 23:42:50 2010 @@ -128,8 +128,7 @@ class FakeWarmRunnerDesc: cpu = FakeCPU() red_args_types = ["int", "float"] - class metainterp_sd: - virtualizable_info = None + virtualizable_info = None # state = WarmEnterState(FakeWarmRunnerDesc()) set_future_values = state.make_set_future_values() Modified: pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py Tue Jun 8 23:42:50 2010 @@ -5,7 +5,6 @@ from pypy.rlib.jit import PARAMETERS, dont_look_inside from pypy.jit.metainterp.jitprof import Profiler from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.ootypesystem import ootype class TranslationTest: @@ -40,7 +39,7 @@ def can_inline(): return False - jitdriver = JitDriver(greens = [], reds = ['frame', 'total'], + jitdriver = JitDriver(greens = [], reds = ['total', 'frame'], virtualizables = ['frame'], get_jitcell_at=get_jitcell_at, set_jitcell_at=set_jitcell_at, Modified: pypy/trunk/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/typesystem.py (original) +++ pypy/trunk/pypy/jit/metainterp/typesystem.py Tue Jun 8 23:42:50 2010 @@ -4,6 +4,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import r_dict def deref(T): @@ -44,9 +45,9 @@ BASETYPE = llmemory.GCREF BoxRef = history.BoxPtr ConstRef = history.ConstPtr - ConstAddr = history.ConstAddr loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstPtr(history.ConstPtr.value) + NULLREF = history.ConstPtr.value + CONST_NULL = history.ConstPtr(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -71,17 +72,16 @@ def cast_fnptr_to_root(self, fnptr): return llmemory.cast_ptr_to_adr(fnptr) - def cls_of_box(self, cpu, box): + def cls_of_box(self, box): obj = box.getref(lltype.Ptr(rclass.OBJECT)) cls = llmemory.cast_ptr_to_adr(obj.typeptr) - return history.ConstInt(cpu.cast_adr_to_int(cls)) + return history.ConstInt(heaptracker.adr2int(cls)) - def subclassOf(self, cpu, clsbox1, clsbox2): - adr = clsbox2.getaddr(cpu) + def instanceOf(self, instbox, clsbox): + adr = clsbox.getaddr() bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - adr = clsbox1.getaddr(cpu) - real_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - return rclass.ll_issubclass(real_class, bounding_class) + real_instance = instbox.getref(rclass.OBJECTPTR) + return rclass.ll_isinstance(real_instance, bounding_class) def get_exception_box(self, etype): return history.ConstInt(etype) @@ -120,7 +120,7 @@ def cast_vtable_to_hashable(self, cpu, ptr): adr = llmemory.cast_ptr_to_adr(ptr) - return cpu.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) def cast_from_ref(self, TYPE, value): return lltype.cast_opaque_ptr(TYPE, value) @@ -130,8 +130,8 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): - return box.getaddr(cpu) + def getaddr_for_box(self, box): + return box.getaddr() def rd_eq(ref1, ref2): return ref1 == ref2 @@ -151,9 +151,9 @@ BASETYPE = ootype.Object BoxRef = history.BoxObj ConstRef = history.ConstObj - ConstAddr = history.ConstObj loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstObj(history.ConstObj.value) + NULLREF = history.ConstObj.value + CONST_NULL = history.ConstObj(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -233,7 +233,7 @@ return ootype.cast_to_object(value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): + def getaddr_for_box(self, box): return box.getref_base() llhelper = LLTypeHelper() Modified: pypy/trunk/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/trunk/pypy/jit/metainterp/virtualizable.py Tue Jun 8 23:42:50 2010 @@ -72,6 +72,10 @@ for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] + self.static_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)]) + self.array_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.array_field_descrs)]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem @@ -102,6 +106,52 @@ i = i + 1 assert len(boxes) == i + 1 # + def write_from_resume_data_partial(virtualizable, reader, nums): + # Load values from the reader (see resume.py) described by + # the list of numbers 'nums', and write them in their proper + # place in the 'virtualizable'. This works from the end of + # the list and returns the index in 'nums' of the start of + # the virtualizable data found, allowing the caller to do + # further processing with the start of the list. + i = len(nums) - 1 + assert i >= 0 + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i]) + setarrayitem(lst, j, x) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(FIELDTYPE, nums[i]) + setattr(virtualizable, fieldname, x) + return i + # + def load_list_of_boxes(virtualizable, reader, nums): + # Uses 'virtualizable' only to know the length of the arrays; + # does not write anything into it. The returned list is in + # the format expected of virtualizable_boxes, so it ends in + # the virtualizable itself. + i = len(nums) - 1 + assert i >= 0 + boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])] + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i]) + boxes.append(box) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(FIELDTYPE, nums[i]) + boxes.append(box) + boxes.reverse() + return boxes + # def check_boxes(virtualizable, boxes): # for debugging i = 0 @@ -141,8 +191,14 @@ static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) + unroll_static_fields_rev = unrolling_iterable( + reversed(list(unroll_static_fields))) + unroll_array_fields_rev = unrolling_iterable( + reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes + self.write_from_resume_data_partial = write_from_resume_data_partial + self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length @@ -172,6 +228,9 @@ return self.cpu.ts.cast_to_instance_maybe(self.VTYPEPTR, virtualizable) cast_to_vtype._annspecialcase_ = 'specialize:ll' + def cast_gcref_to_vtype(self, virtualizable): + return lltype.cast_opaque_ptr(self.VTYPEPTR, virtualizable) + def is_vtypeptr(self, TYPE): return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR) @@ -212,12 +271,6 @@ assert virtualizable.vable_token == self.TOKEN_NONE force_now._dont_inline_ = True - def forced_vable(self, virtualizable_boxes): - virtualizable_box = virtualizable_boxes[-1] - virtualizable = self.unwrap_virtualizable_box(virtualizable_box) - self.write_boxes(virtualizable, virtualizable_boxes) - virtualizable.vable_token = self.TOKEN_NONE - # ____________________________________________________________ # # The 'vable_token' field of a virtualizable is either 0, -1, or points Modified: pypy/trunk/pypy/jit/metainterp/virtualref.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/virtualref.py (original) +++ pypy/trunk/pypy/jit/metainterp/virtualref.py Tue Jun 8 23:42:50 2010 @@ -1,6 +1,7 @@ from pypy.rpython.rmodel import inputconst, log from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker class VirtualRefInfo: @@ -20,7 +21,8 @@ 'jit_virtual_ref') # build some constants adr = llmemory.cast_ptr_to_adr(self.jit_virtual_ref_vtable) - self.jit_virtual_ref_const_class = history.ConstAddr(adr, self.cpu) + adr = heaptracker.adr2int(adr) + self.jit_virtual_ref_const_class = history.ConstInt(adr) fielddescrof = self.cpu.fielddescrof self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF, 'virtual_token') @@ -60,11 +62,11 @@ # The 'virtual_token' field has the same meaning as the 'vable_token' field # of a virtualizable. It is equal to: - # * -2 (TOKEN_NONE) when tracing, except as described below; + # * -3 (TOKEN_NONE) when tracing, except as described below; # * -1 (TOKEN_TRACING_RESCALL) during tracing when we do a residual call; # * addr in the CPU stack (set by FORCE_TOKEN) when running the assembler; - # * -2 (TOKEN_NONE) after the virtual is forced, if it is forced at all. - TOKEN_NONE = -2 + # * -3 (TOKEN_NONE) after the virtual is forced, if it is forced at all. + TOKEN_NONE = -3 TOKEN_TRACING_RESCALL = -1 def virtual_ref_during_tracing(self, real_object): @@ -104,16 +106,6 @@ # marker "modified during residual call" set. return True - def forced_single_vref(self, gcref, real_object): - if not self.is_virtual_ref(gcref): - return - assert real_object - vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) - assert (vref.virtual_token != self.TOKEN_NONE and - vref.virtual_token != self.TOKEN_TRACING_RESCALL) - vref.virtual_token = self.TOKEN_NONE - vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) - def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Tue Jun 8 23:42:50 2010 @@ -16,12 +16,13 @@ from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.unsimplify import call_final_function -from pypy.jit.metainterp import codewriter -from pypy.jit.metainterp import support, history, pyjitpl, gc +from pypy.jit.metainterp import history, pyjitpl, gc from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp -from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler +from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.codewriter import support, codewriter +from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE # ____________________________________________________________ @@ -130,9 +131,6 @@ stats.maybe_view() stats.check_consistency() -class JitException(Exception): - _go_through_llinterp_uncaught_ = True # ugh - class ContinueRunningNormallyBase(JitException): pass @@ -144,47 +142,49 @@ class WarmRunnerDesc(object): def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, - optimizer=None, **kwds): + optimizer=None, ProfilerClass=EmptyProfiler, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! - if policy is None: - policy = JitPolicy() self.set_translator(translator) + self.build_cpu(CPUClass, **kwds) self.find_portal() - self.codewriter = codewriter.CodeWriter(self.rtyper) - graphs = self.codewriter.find_all_graphs(self.portal_graph, - policy, - CPUClass.supports_floats) + self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + if policy is None: + policy = JitPolicy() + policy.set_supports_floats(self.cpu.supports_floats) + graphs = self.codewriter.find_all_graphs(policy) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) - self.build_meta_interp(CPUClass, **kwds) + self.build_meta_interp(ProfilerClass) self.make_args_specification() # from pypy.jit.metainterp.virtualref import VirtualRefInfo - self.metainterp_sd.virtualref_info = VirtualRefInfo(self) + vrefinfo = VirtualRefInfo(self) + self.codewriter.setup_vrefinfo(vrefinfo) if self.jitdriver.virtualizables: from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.metainterp_sd.virtualizable_info = VirtualizableInfo(self) + self.virtualizable_info = VirtualizableInfo(self) + self.codewriter.setup_virtualizable_info(self.virtualizable_info) + else: + self.virtualizable_info = None # self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_function() self.rewrite_jit_merge_point(policy) - - self.codewriter.generate_bytecode(self.metainterp_sd, - self.portal_graph, - self.portal_runner_ptr - ) + + verbose = not self.cpu.translate_support_code + self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jit() self.rewrite_set_param() - self.rewrite_force_virtual() + self.rewrite_force_virtual(vrefinfo) self.add_finish() - self.metainterp_sd.finish_setup(optimizer=optimizer) + self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info if vinfo is not None: vinfo.finish() if self.cpu.translate_support_code: @@ -244,11 +244,10 @@ remove_asserts=True, really_remove_asserts=True) - def build_meta_interp(self, CPUClass, translate_support_code=False, - view="auto", no_stats=False, - ProfilerClass=EmptyProfiler, **kwds): + def build_cpu(self, CPUClass, translate_support_code=False, + no_stats=False, **kwds): assert CPUClass is not None - opt = history.Options(**kwds) + self.opt = history.Options(**kwds) if no_stats: stats = history.NoStats() else: @@ -259,18 +258,18 @@ annhelper = self.annhelper else: annhelper = None - cpu = CPUClass(self.translator.rtyper, self.stats, opt, + cpu = CPUClass(self.translator.rtyper, self.stats, self.opt, translate_support_code, gcdescr=self.gcdescr) self.cpu = cpu - self.metainterp_sd = MetaInterpStaticData(self.portal_graph, # xxx - cpu, - self.stats, opt, + + def build_meta_interp(self, ProfilerClass): + self.metainterp_sd = MetaInterpStaticData(self.cpu, + self.opt, ProfilerClass=ProfilerClass, warmrunnerdesc=self) def make_exception_classes(self): - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(self.PORTAL_FUNCTYPE.ARGS)]) + class DoneWithThisFrameVoid(JitException): def __str__(self): return 'DoneWithThisFrameVoid()' @@ -304,18 +303,19 @@ return 'ExitFrameWithExceptionRef(%s)' % (self.value,) class ContinueRunningNormally(ContinueRunningNormallyBase): - def __init__(self, argboxes): - # accepts boxes as argument, but unpacks them immediately - # before we raise the exception -- the boxes' values will - # be modified in a 'finally' by restore_patched_boxes(). - from pypy.jit.metainterp.warmstate import unwrap - for i, name, ARG in portalfunc_ARGS: - v = unwrap(ARG, argboxes[i]) - setattr(self, name, v) - + def __init__(self, gi, gr, gf, ri, rr, rf): + # the six arguments are: lists of green ints, greens refs, + # green floats, red ints, red refs, and red floats. + self.green_int = gi + self.green_ref = gr + self.green_float = gf + self.red_int = ri + self.red_ref = rr + self.red_float = rf def __str__(self): - return 'ContinueRunningNormally(%s)' % ( - ', '.join(map(str, self.args)),) + return 'ContinueRunningNormally(%s, %s, %s, %s, %s, %s)' % ( + self.green_int, self.green_ref, self.green_float, + self.red_int, self.red_ref, self.red_float) self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt @@ -411,17 +411,10 @@ def make_args_specification(self): graph, block, index = self.jit_merge_point_pos op = block.operations[index] - args = op.args[2:] - ALLARGS = [] - self.green_args_spec = [] - self.red_args_types = [] - for i, v in enumerate(args): - TYPE = v.concretetype - ALLARGS.append(TYPE) - if i < len(self.jitdriver.greens): - self.green_args_spec.append(TYPE) - else: - self.red_args_types.append(history.getkind(TYPE)) + greens_v, reds_v = support.decode_hp_hint_args(op) + ALLARGS = [v.concretetype for v in (greens_v + reds_v)] + self.green_args_spec = [v.concretetype for v in greens_v] + self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] self.num_green_args = len(self.green_args_spec) RESTYPE = graph.getreturnvar().concretetype (self.JIT_ENTER_FUNCTYPE, @@ -443,7 +436,7 @@ continue op = block.operations[index] - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) args_v = greens_v + reds_v vlist = [Constant(jit_enter_fnptr, FUNCPTR)] + args_v @@ -500,13 +493,24 @@ # ____________________________________________________________ # Prepare the portal_runner() helper # + from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) self.portal_ptr = portal_ptr - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)]) - - + # + portalfunc_ARGS = [] + nums = {} + for i, ARG in enumerate(PORTALFUNC.ARGS): + if i < len(self.jitdriver.greens): + color = 'green' + else: + color = 'red' + attrname = '%s_%s' % (color, history.getkind(ARG)) + count = nums.get(attrname, 0) + nums[attrname] = count + 1 + portalfunc_ARGS.append((ARG, attrname, count)) + portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS) + # rtyper = self.translator.rtyper RESULT = PORTALFUNC.RESULT result_kind = history.getkind(RESULT) @@ -520,21 +524,22 @@ portal_ptr)(*args) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -550,8 +555,9 @@ self.PTR_PORTAL_FUNCTYPE.TO, self.PTR_PORTAL_FUNCTYPE.TO.ARGS, self.PTR_PORTAL_FUNCTYPE.TO.RESULT) + self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -565,22 +571,23 @@ fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) return ll_portal_runner(*args) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -607,7 +614,7 @@ op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v @@ -651,22 +658,8 @@ op.opname = 'direct_call' op.args[:3] = [closures[funcname]] - def rewrite_force_virtual(self): + def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': py.test.skip("rewrite_force_virtual: port it to ootype") all_graphs = self.translator.graphs - vrefinfo = self.metainterp_sd.virtualref_info vrefinfo.replace_force_virtual_with_call(all_graphs) - - -def decode_hp_hint_args(op): - # Returns (list-of-green-vars, list-of-red-vars) without Voids. - assert op.opname == 'jit_marker' - jitdriver = op.args[1].value - numgreens = len(jitdriver.greens) - numreds = len(jitdriver.reds) - greens_v = op.args[2:2+numgreens] - reds_v = op.args[2+numgreens:] - assert len(reds_v) == numreds - return ([v for v in greens_v if v.concretetype is not lltype.Void], - [v for v in reds_v if v.concretetype is not lltype.Void]) Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmstate.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmstate.py Tue Jun 8 23:42:50 2010 @@ -11,11 +11,26 @@ from pypy.rlib.jit import DEBUG_PROFILE from pypy.rlib.jit import BaseJitCell from pypy.rlib.debug import debug_start, debug_stop, debug_print -from pypy.jit.metainterp import support, history +from pypy.jit.metainterp import history +from pypy.jit.codewriter import support, heaptracker # ____________________________________________________________ @specialize.arg(0) +def specialize_value(TYPE, x): + """'x' must be a Signed, a GCREF or a Float. + This function casts it to a more specialized type, like Char or Ptr(..). + """ + INPUT = lltype.typeOf(x) + if INPUT is lltype.Signed: + return lltype.cast_primitive(TYPE, x) # XXX missing: Ptr(non-gc) + elif INPUT is lltype.Float: + assert TYPE is lltype.Float + return x + else: + return lltype.cast_opaque_ptr(TYPE, x) + + at specialize.arg(0) def unwrap(TYPE, box): if TYPE is lltype.Void: return None @@ -39,7 +54,7 @@ return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) - value = cpu.cast_adr_to_int(adr) + value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) @@ -180,7 +195,7 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = metainterp_sd.virtualizable_info + vinfo = self.warmrunnerdesc.virtualizable_info num_green_args = self.warmrunnerdesc.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() @@ -401,7 +416,7 @@ warmrunnerdesc = self.warmrunnerdesc cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.metainterp_sd.virtualizable_info + vinfo = warmrunnerdesc.virtualizable_info red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) # def set_future_values(*redargs): Modified: pypy/trunk/pypy/jit/tl/spli/interpreter.py ============================================================================== --- pypy/trunk/pypy/jit/tl/spli/interpreter.py (original) +++ pypy/trunk/pypy/jit/tl/spli/interpreter.py Tue Jun 8 23:42:50 2010 @@ -24,7 +24,7 @@ unrolling_compare_dispatch_table = unrolling_iterable( enumerate(compare_ops)) -jitdriver = JitDriver(greens = ['code', 'instr_index'], +jitdriver = JitDriver(greens = ['instr_index', 'code'], reds = ['frame'], virtualizables = ['frame']) Modified: pypy/trunk/pypy/jit/tl/tl.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tl.py (original) +++ pypy/trunk/pypy/jit/tl/tl.py Tue Jun 8 23:42:50 2010 @@ -56,7 +56,7 @@ def make_interp(supports_call): myjitdriver = JitDriver(greens = ['pc', 'code'], - reds = ['stack', 'inputarg'], + reds = ['inputarg', 'stack'], virtualizables = ['stack']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): Modified: pypy/trunk/pypy/jit/tl/tla/tla.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tla/tla.py (original) +++ pypy/trunk/pypy/jit/tl/tla/tla.py Tue Jun 8 23:42:50 2010 @@ -71,10 +71,10 @@ # ____________________________________________________________ -def get_printable_location(bytecode, pc): +def get_printable_location(pc, bytecode): return str(pc) -jitdriver = JitDriver(greens=['bytecode', 'pc'], +jitdriver = JitDriver(greens=['pc', 'bytecode'], reds=['self'], virtualizables=['self'], get_printable_location=get_printable_location) Modified: pypy/trunk/pypy/jit/tl/tlc.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tlc.py (original) +++ pypy/trunk/pypy/jit/tl/tlc.py Tue Jun 8 23:42:50 2010 @@ -226,7 +226,7 @@ def make_interp(supports_call, jitted=True): - myjitdriver = JitDriver(greens = ['code', 'pc'], + myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['frame', 'pool']) def interp(code='', pc=0, inputarg=0, pool=None): Modified: pypy/trunk/pypy/jit/tl/tlr.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tlr.py (original) +++ pypy/trunk/pypy/jit/tl/tlr.py Tue Jun 8 23:42:50 2010 @@ -12,7 +12,7 @@ NEG_A = 8 class TLRJitDriver(JitDriver): - greens = ['bytecode', 'pc'] + greens = ['pc', 'bytecode'] reds = ['a', 'regs'] tlrjitdriver = TLRJitDriver() Modified: pypy/trunk/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/trunk/pypy/jit/tool/jitoutput.py (original) +++ pypy/trunk/pypy/jit/tool/jitoutput.py Tue Jun 8 23:42:50 2010 @@ -21,8 +21,6 @@ (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), - (('blackholed_ops.total',), '^blackholed ops:\s+(\d+)$'), - (('blackholed_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), (('forcings',), '^forcings:\s+(\d+)$'), @@ -62,7 +60,6 @@ def __init__(self): self.ops = Ops() self.recorded_ops = Ops() - self.blackholed_ops = Ops() self.abort = Aborts() def parse_prof(output): Modified: pypy/trunk/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/trunk/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/trunk/pypy/jit/tool/test/test_jitoutput.py Tue Jun 8 23:42:50 2010 @@ -41,8 +41,6 @@ assert info.recorded_ops.calls == 0 assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 - assert info.blackholed_ops.total == 0 - assert info.blackholed_ops.pure_calls == 0 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 0 @@ -59,8 +57,6 @@ calls: 3 pure calls: 2 guards: 1 -blackholed ops: 5 - pure calls: 3 opt ops: 6 opt guards: 1 forcings: 1 @@ -87,8 +83,6 @@ assert info.recorded_ops.calls == 3 assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 - assert info.blackholed_ops.total == 5 - assert info.blackholed_ops.pure_calls == 3 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 1 Modified: pypy/trunk/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/trunk/pypy/module/pypyjit/policy.py (original) +++ pypy/trunk/pypy/module/pypyjit/policy.py Tue Jun 8 23:42:50 2010 @@ -1,4 +1,4 @@ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy class PyPyJitPolicy(JitPolicy): Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py ============================================================================== --- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py (original) +++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py Tue Jun 8 23:42:50 2010 @@ -222,7 +222,7 @@ while i < n+OFFSET: i = f(f(i)) return i - ''', 96, + ''', 98, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOAD_GLOBAL") @@ -263,7 +263,7 @@ x = a.f(i) i = a.f(x) return i - ''', 92, + ''', 93, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOOKUP_METHOD") @@ -308,7 +308,7 @@ x = a.f(i) i = a.g(x) return i - ''', 105, + ''', 106, ([20], 20), ([31], 31)) ops = self.get_by_bytecode("LOOKUP_METHOD") Modified: pypy/trunk/pypy/objspace/flow/model.py ============================================================================== --- pypy/trunk/pypy/objspace/flow/model.py (original) +++ pypy/trunk/pypy/objspace/flow/model.py Tue Jun 8 23:42:50 2010 @@ -416,13 +416,14 @@ lst.append(link) return result -def copygraph(graph, shallow=False, varmap={}): +def copygraph(graph, shallow=False, varmap={}, shallowvars=False): "Make a copy of a flow graph." blockmap = {} varmap = varmap.copy() + shallowvars = shallowvars or shallow def copyvar(v): - if shallow: + if shallowvars: return v try: return varmap[v] Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Tue Jun 8 23:42:50 2010 @@ -111,16 +111,14 @@ self.traceback_frames = [] lines = [] for frame in frames: - logline = frame.graph.name + logline = frame.graph.name + "()" if frame.curr_block is None: logline += " " lines.append(logline) continue try: - logline += " " + self.typer.annotator.annotated[frame.curr_block].__module__ - except (KeyError, AttributeError): - # if the graph is from the GC it was not produced by the same - # translator :-( + logline += " " + self.typer.annotator.annotated[frame.curr_block].func.__module__ + except (KeyError, AttributeError, TypeError): logline += " " lines.append(logline) for i, operation in enumerate(frame.curr_block.operations): @@ -808,9 +806,9 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) - def op_cast_adr_to_int(self, adr): + def op_cast_adr_to_int(self, adr, mode): checkadr(adr) - return llmemory.cast_adr_to_int(adr) + return llmemory.cast_adr_to_int(adr, mode) def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Tue Jun 8 23:42:50 2010 @@ -505,7 +505,7 @@ # additionally, this adds mess to __del__ "semantics" _all_callbacks = {} _all_callbacks_results = [] -_callback2obj = {} +_int2obj = {} _callback_exc_info = None def get_rtyper(): @@ -522,6 +522,13 @@ """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) + if isinstance(llobj, llmemory.AddressAsInt): + cobj = ctypes.cast(lltype2ctypes(llobj.adr), ctypes.c_void_p) + res = intmask(cobj.value) + _int2obj[res] = llobj.adr.ptr._obj + return res + if isinstance(llobj, llmemory.fakeaddress): + llobj = llobj.ptr or 0 T = lltype.typeOf(llobj) @@ -614,8 +621,9 @@ else: ctypes_func_type = get_ctypes_type(T) res = ctypes_func_type(callback) - _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container _all_callbacks[key] = res + key2 = intmask(ctypes.cast(res, ctypes.c_void_p).value) + _int2obj[key2] = container return res index = 0 @@ -724,9 +732,9 @@ container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): - cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value - if cobjkey in _callback2obj: - container = _callback2obj[cobjkey] + cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value) + if cobjkey in _int2obj: + container = _int2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), @@ -993,6 +1001,8 @@ """Cast a value to a result type, trying to use the same rules as C.""" if not isinstance(RESTYPE, lltype.LowLevelType): raise TypeError("rffi.cast() first arg should be a TYPE") + if isinstance(value, llmemory.AddressAsInt): + value = value.adr if isinstance(value, llmemory.fakeaddress): value = value.ptr or 0 TYPE1 = lltype.typeOf(value) Modified: pypy/trunk/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/llarena.py Tue Jun 8 23:42:50 2010 @@ -223,7 +223,8 @@ else: return self.arena._getid() < arena._getid() - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): + assert not symbolic return self.arena._getid() + self.offset Modified: pypy/trunk/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/llmemory.py Tue Jun 8 23:42:50 2010 @@ -7,6 +7,7 @@ import weakref from pypy.rlib.objectmodel import Symbolic from pypy.rpython.lltypesystem import lltype +from pypy.tool.uid import uid class AddressOffset(Symbolic): @@ -478,11 +479,14 @@ else: return lltype.nullptr(EXPECTED_TYPE.TO) - def _cast_to_int(self): - # This is a bit annoying. We want this method to still work when the - # pointed-to object is dead + def _cast_to_int(self, symbolic=False): if self: - return self.ptr._cast_to_int(False) + if symbolic: + return AddressAsInt(self) + else: + # This is a bit annoying. We want this method to still work + # when the pointed-to object is dead + return self.ptr._cast_to_int(False) else: return 0 @@ -496,6 +500,29 @@ # ____________________________________________________________ +class AddressAsInt(Symbolic): + # a symbolic, rendered as an address cast to an integer. + def __init__(self, adr): + self.adr = adr + def annotation(self): + from pypy.annotation import model + return model.SomeInteger() + def lltype(self): + return lltype.Signed + def __eq__(self, other): + return self.adr == cast_int_to_adr(other) + def __ne__(self, other): + return self.adr != cast_int_to_adr(other) + def __nonzero__(self): + return bool(self.adr) + def __repr__(self): + try: + return '' % (self.adr.ptr,) + except AttributeError: + return '' % (uid(self),) + +# ____________________________________________________________ + class NullAddressError(Exception): pass @@ -603,12 +630,31 @@ def cast_adr_to_ptr(adr, EXPECTED_TYPE): return adr._cast_to_ptr(EXPECTED_TYPE) -def cast_adr_to_int(adr): - return adr._cast_to_int() +def cast_adr_to_int(adr, mode="emulated"): + # The following modes are supported before translation (after + # translation, it's all just a cast): + # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some + # number based on id(). The difference is that it works even if the + # address is that of a dead object. + # * mode="symbolic": returns an AddressAsInt instance, which can only be + # cast back to an address later. + # * mode="forced": uses rffi.cast() to return a real number. + assert mode in ("emulated", "symbolic", "forced") + res = adr._cast_to_int(symbolic = (mode != "emulated")) + if mode == "forced": + from pypy.rpython.lltypesystem.rffi import cast + res = cast(lltype.Signed, res) + return res _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + if isinstance(int, AddressAsInt): + return int.adr + try: + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + except ValueError: + from pypy.rpython.lltypesystem import ll2ctypes + ptr = ll2ctypes._int2obj[int]._as_ptr() return cast_ptr_to_adr(ptr) # ____________________________________________________________ Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Tue Jun 8 23:42:50 2010 @@ -263,7 +263,7 @@ 'uint_rshift': LLOp(canfold=True), 'uint_xor': LLOp(canfold=True), - 'float_is_true': LLOp(canfold=True), + 'float_is_true': LLOp(canfold=True), # it really means "x != 0.0" 'float_neg': LLOp(canfold=True), 'float_abs': LLOp(canfold=True), @@ -410,7 +410,7 @@ 'cast_ptr_to_adr': LLOp(sideeffects=False), 'cast_adr_to_ptr': LLOp(canfold=True), 'cast_adr_to_int': LLOp(sideeffects=False), - 'cast_int_to_adr': LLOp(canfold=True), # not implemented in llinterp + 'cast_int_to_adr': LLOp(canfold=True), 'get_group_member': LLOp(canfold=True), 'get_next_group_member':LLOp(canfold=True), Modified: pypy/trunk/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lltype.py Tue Jun 8 23:42:50 2010 @@ -301,9 +301,17 @@ class RttiStruct(Struct): _runtime_type_info = None + def _install_extras(self, rtti=False, **kwds): + if rtti: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, + name=self._name, + about=self)._obj + Struct._install_extras(self, **kwds) + def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + raise TypeError("attachRuntimeTypeInfo: %r must have been built " + "with the rtti=True argument" % (self,)) if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -1877,7 +1885,8 @@ def cast_int_to_ptr(PTRTYPE, oddint): if oddint == 0: return nullptr(PTRTYPE.TO) - assert oddint & 1, "only odd integers can be cast back to ptr" + if not (oddint & 1): + raise ValueError("only odd integers can be cast back to ptr") return _ptr(PTRTYPE, oddint, solid=True) def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Tue Jun 8 23:42:50 2010 @@ -13,7 +13,7 @@ Ptr, Struct, GcStruct, malloc, \ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ - Array, Char, Void, attachRuntimeTypeInfo, \ + Array, Char, Void, \ FuncType, Bool, Signed, functionptr, FuncType, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -60,7 +60,8 @@ CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), hints = {'immutable': True, 'shouldntbenull': True, - 'typeptr': True}) + 'typeptr': True}, + rtti = True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), @@ -72,7 +73,7 @@ hints = {'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) -NONGCOBJECTPTR = Ptr(OBJECT) +NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} @@ -348,18 +349,20 @@ if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) + kwds = {} + if self.gcflavor == 'gc': + kwds['rtti'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, - *llfields) + *llfields, + **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields - if self.gcflavor == 'gc': - attachRuntimeTypeInfo(self.object_type) def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Tue Jun 8 23:42:50 2010 @@ -1242,6 +1242,15 @@ res = interpret(f, []) assert res == 6 + def test_force_to_int(self): + S = lltype.Struct('S') + p = lltype.malloc(S, flavor='raw') + a = llmemory.cast_ptr_to_adr(p) + i = llmemory.cast_adr_to_int(a, "forced") + assert type(i) is int + assert i == llmemory.cast_adr_to_int(a, "forced") + lltype.free(p, flavor='raw') + class TestPlatform(object): def test_lib_on_libpaths(self): from pypy.translator.platform import platform Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_llmemory.py Tue Jun 8 23:42:50 2010 @@ -624,3 +624,24 @@ # the following line crashes if the array is dead ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) ptr1[0] = NULL + +def test_cast_adr_to_int(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + i = cast_adr_to_int(adr, mode="symbolic") + assert isinstance(i, AddressAsInt) + assert cast_int_to_adr(i) == adr + assert cast_adr_to_int(NULL, mode="symbolic") == 0 + assert cast_int_to_adr(0) == NULL + # + i = cast_adr_to_int(adr, mode="emulated") + assert type(i) is int + i = cast_adr_to_int(NULL, mode="emulated") + assert type(i) is int and i == 0 + # + i = cast_adr_to_int(adr, mode="forced") + assert type(i) is int + #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details + i = cast_adr_to_int(NULL, mode="forced") + assert type(i) is int and i == 0 Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py Tue Jun 8 23:42:50 2010 @@ -363,22 +363,25 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) py.test.raises(ValueError, "getRuntimeTypeInfo(S)") - pinf0 = attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) + pinfx = getRuntimeTypeInfo(S) + pinf0 = attachRuntimeTypeInfo(S) # no-op, really assert pinf0._obj.about == S + assert pinf0 == pinfx pinf = getRuntimeTypeInfo(S) assert pinf == pinf0 pinf1 = getRuntimeTypeInfo(S) assert pinf == pinf1 - Z = GcStruct('z', ('x', Unsigned)) - attachRuntimeTypeInfo(Z) + Z = GcStruct('z', ('x', Unsigned), rtti=True) assert getRuntimeTypeInfo(Z) != pinf0 - Sbis = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(Sbis) + Sbis = GcStruct('s', ('x', Signed), rtti=True) assert getRuntimeTypeInfo(Sbis) != pinf0 assert Sbis != S # the attached runtime type info distinguishes them + Ster = GcStruct('s', ('x', Signed), rtti=True) + assert Sbis != Ster # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -399,12 +402,12 @@ assert pinf._obj.query_funcptr == qp def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) attachRuntimeTypeInfo(S) s = malloc(S) s.x = 0 assert runtime_type_info(s) == getRuntimeTypeInfo(S) - S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + S1 = GcStruct('s1', ('sub', S), ('x', Signed), rtti=True) attachRuntimeTypeInfo(S1) s1 = malloc(S1) s1.sub.x = 0 Modified: pypy/trunk/pypy/rpython/memory/gctransform/test/test_boehm.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/test/test_boehm.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/test/test_boehm.py Tue Jun 8 23:42:50 2010 @@ -40,7 +40,7 @@ assert f is not None def test_boehm_finalizer___del__(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -58,7 +58,8 @@ assert f is not None def test_boehm_finalizer_nomix___del___and_pyobj(): - S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) + S = lltype.GcStruct("S", ('x', lltype.Signed), + ('y', lltype.Ptr(lltype.PyObject)), rtti=True) def f(s): s.x = 1 def type_info_S(p): Modified: pypy/trunk/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/test/test_refcounting.py Tue Jun 8 23:42:50 2010 @@ -175,7 +175,7 @@ assert len(ops['gc_free']) == 1 def test_deallocator_with_destructor(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -192,9 +192,9 @@ graph, t = make_deallocator(S) def test_caching_dynamic_deallocator(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) - T = lltype.GcStruct("T", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) + S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) + T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): Modified: pypy/trunk/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/trunk/pypy/rpython/memory/test/test_lldict.py Tue Jun 8 23:42:50 2010 @@ -100,7 +100,7 @@ _TYPE = llmemory.Address def __init__(self, intval): self.intval = intval - def _cast_to_int(self): + def _cast_to_int(self, symbolic="?"): return self.intval def __repr__(self): return '' % (self.intval & (sys.maxint*2+1),) Modified: pypy/trunk/pypy/rpython/raddress.py ============================================================================== --- pypy/trunk/pypy/rpython/raddress.py (original) +++ pypy/trunk/pypy/rpython/raddress.py Tue Jun 8 23:42:50 2010 @@ -7,6 +7,8 @@ from pypy.rpython.rptr import PtrRepr from pypy.rpython.lltypesystem import lltype from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.objectmodel import we_are_translated + class __extend__(annmodel.SomeAddress): def rtyper_makerepr(self, rtyper): @@ -33,7 +35,7 @@ def ll_str(self, a): from pypy.rpython.lltypesystem.rstr import ll_str - id = cast_adr_to_int(a) + id = ll_addrhash(a) return ll_str.ll_int2hex(r_uint(id), True) def rtype_getattr(self, hop): @@ -55,7 +57,7 @@ get_ll_fasthash_function = get_ll_hash_function def ll_addrhash(addr1): - return cast_adr_to_int(addr1) + return cast_adr_to_int(addr1, "forced") address_repr = AddressRepr() Modified: pypy/trunk/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/rbuiltin.py Tue Jun 8 23:42:50 2010 @@ -637,9 +637,14 @@ def rtype_cast_adr_to_int(hop): assert isinstance(hop.args_r[0], raddress.AddressRepr) - adr, = hop.inputargs(hop.args_r[0]) + adr = hop.inputarg(hop.args_r[0], arg=0) + if len(hop.args_s) == 1: + mode = "emulated" + else: + mode = hop.args_s[1].const hop.exception_cannot_occur() - return hop.genop('cast_adr_to_int', [adr], + return hop.genop('cast_adr_to_int', + [adr, hop.inputconst(lltype.Void, mode)], resulttype = lltype.Signed) def rtype_cast_int_to_adr(hop): Modified: pypy/trunk/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_exception.py (original) +++ pypy/trunk/pypy/rpython/test/test_exception.py Tue Jun 8 23:42:50 2010 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.llinterp import LLException +from pypy.rpython.error import MissingRTypeOperation class MyException(Exception): pass @@ -125,7 +126,18 @@ class TestLLtype(BaseTestException, LLRtypeMixin): - pass + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + def g(): + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise lle # instead, must cast back from a base ptr to an instance + def f(): + try: + g() + except OverflowError: + return 42 + py.test.raises(MissingRTypeOperation, self.interpret, f, []) class TestOOtype(BaseTestException, OORtypeMixin): pass Modified: pypy/trunk/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_llann.py (original) +++ pypy/trunk/pypy/rpython/test/test_llann.py Tue Jun 8 23:42:50 2010 @@ -343,8 +343,7 @@ assert s.items[1].const == 3 def test_getRuntimeTypeInfo(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(): return getRuntimeTypeInfo(S) s = self.annotate(llf, []) @@ -353,8 +352,7 @@ assert s.const == getRuntimeTypeInfo(S) def test_runtime_type_info(self): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def llf(p): return runtime_type_info(p) s = self.annotate(llf, [annmodel.SomePtr(Ptr(S))]) Modified: pypy/trunk/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rdict.py (original) +++ pypy/trunk/pypy/rpython/test/test_rdict.py Tue Jun 8 23:42:50 2010 @@ -781,6 +781,24 @@ assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2) assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3) + def test_dict_of_addresses(self): + from pypy.rpython.lltypesystem import llmemory + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def func(i): + d = {} + d[llmemory.cast_ptr_to_adr(a)] = 123 + d[llmemory.cast_ptr_to_adr(b)] = 456 + if i > 5: + key = llmemory.cast_ptr_to_adr(a) + else: + key = llmemory.cast_ptr_to_adr(b) + return d[key] + + assert self.interpret(func, [3]) == 456 + def test_prebuilt_list_of_addresses(self): from pypy.rpython.lltypesystem import llmemory Modified: pypy/trunk/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rptr.py (original) +++ pypy/trunk/pypy/rpython/test/test_rptr.py Tue Jun 8 23:42:50 2010 @@ -36,8 +36,7 @@ assert s.ll_ptrtype == PS2 def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def ll_example(p): return (runtime_type_info(p), runtime_type_info(p) == getRuntimeTypeInfo(S)) @@ -176,6 +175,31 @@ res = interpret(fn, [5]) assert res is True +def test_cast_adr_to_int(): + S = Struct('S') + p = malloc(S, immortal=True) + def fn(n): + a = llmemory.cast_ptr_to_adr(p) + if n == 2: + return llmemory.cast_adr_to_int(a, "emulated") + elif n == 4: + return llmemory.cast_adr_to_int(a, "symbolic") + else: + return llmemory.cast_adr_to_int(a, "forced") + + res = interpret(fn, [2]) + assert type(res) is int + assert res == cast_ptr_to_int(p) + # + res = interpret(fn, [4]) + assert isinstance(res, llmemory.AddressAsInt) + assert llmemory.cast_int_to_adr(res) == llmemory.cast_ptr_to_adr(p) + # + res = interpret(fn, [6]) + assert type(res) is int + from pypy.rpython.lltypesystem import rffi + assert res == rffi.cast(Signed, p) + def test_flavored_malloc(): T = GcStruct('T', ('y', Signed)) def fn(n): Modified: pypy/trunk/pypy/translator/c/primitive.py ============================================================================== --- pypy/trunk/pypy/translator/c/primitive.py (original) +++ pypy/trunk/pypy/translator/c/primitive.py Tue Jun 8 23:42:50 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ CompositeOffset, ArrayLengthOffset, \ - GCHeaderOffset, GCREF + GCHeaderOffset, GCREF, AddressAsInt from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation from pypy.translator.c.support import cdecl, barebonearray @@ -61,6 +61,8 @@ name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) + elif isinstance(value, AddressAsInt): + return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r"%value) if value is None: Modified: pypy/trunk/pypy/translator/c/src/address.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/address.h (original) +++ pypy/trunk/pypy/translator/c/src/address.h Tue Jun 8 23:42:50 2010 @@ -16,5 +16,5 @@ #define OP_ADR_LT(x,y,r) r = ((x) < (y)) #define OP_ADR_GE(x,y,r) r = ((x) >= (y)) -#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x) -#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) +#define OP_CAST_ADR_TO_INT(x, mode, r) r = ((long)x) +#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) Modified: pypy/trunk/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_genc.py (original) +++ pypy/trunk/pypy/translator/c/test/test_genc.py Tue Jun 8 23:42:50 2010 @@ -144,10 +144,8 @@ assert f1() == '\x00' def test_runtime_type_info(): - S = GcStruct('s', ('is_actually_s1', Bool)) - S1 = GcStruct('s1', ('sub', S)) - attachRuntimeTypeInfo(S) - attachRuntimeTypeInfo(S1) + S = GcStruct('s', ('is_actually_s1', Bool), rtti=True) + S1 = GcStruct('s1', ('sub', S), rtti=True) def rtti_S(p): if p.is_actually_s1: return getRuntimeTypeInfo(S1) Modified: pypy/trunk/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/trunk/pypy/translator/c/test/test_lladdresses.py Tue Jun 8 23:42:50 2010 @@ -193,3 +193,42 @@ fc = compile(f, [int]) res = fc(42) assert res == 0 + +def test_cast_int_to_adr(): + S = lltype.Struct("S", ("x", lltype.Signed)) + s = lltype.malloc(S, immortal=True) + s.x = 42 + integer = cast_adr_to_int(cast_ptr_to_adr(s), mode="symbolic") + def f(n): + if n > 1: + i = integer + else: + i = 123 # nonsense, but never used + print "hello world" # prevent constant-folding + adr = cast_int_to_adr(i) + s = cast_adr_to_ptr(adr, lltype.Ptr(S)) + return s.x + fc = compile(f, [int]) + res = fc(5) + assert res == 42 + +def test_dict_of_addresses(): + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def f(i): + d = {} + d[cast_ptr_to_adr(a)] = 123 + d[cast_ptr_to_adr(b)] = 456 + if i > 5: + key = cast_ptr_to_adr(a) + else: + key = cast_ptr_to_adr(b) + return d[key] + + fc = compile(f, [int]) + res = fc(-77) + assert res == 456 + res = fc(77) + assert res == 123 Modified: pypy/trunk/pypy/translator/c/test/test_refcount.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_refcount.py (original) +++ pypy/trunk/pypy/translator/c/test/test_refcount.py Tue Jun 8 23:42:50 2010 @@ -130,9 +130,8 @@ def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: - S = lltype.GcStruct('S', ('x', lltype.Signed)) + S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): Modified: pypy/trunk/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/trunk/pypy/translator/tool/make_dot.py (original) +++ pypy/trunk/pypy/translator/tool/make_dot.py Tue Jun 8 23:42:50 2010 @@ -152,7 +152,7 @@ shape = "octagon" if block.exitswitch is not None: - lines.append("exitswitch: %s" % block.exitswitch) + lines.append("exitswitch: %s" % (block.exitswitch,)) iargs = " ".join(map(repr, block.inputargs)) if self.VERBOSE: From afa at codespeak.net Tue Jun 8 23:50:58 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:50:58 +0200 (CEST) Subject: [pypy-svn] r75221 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608215058.90141282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:50:56 2010 New Revision: 75221 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: More changes Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:50:56 2010 @@ -361,6 +361,14 @@ type = self.get_type_for_declaration() return 'PyAPI_DATA(%s) %s;' % (type, self.name) + def get_data_definition(self): + type = self.get_type_for_declaration() + if not self.needs_hidden_global_structure: + return ['%s %s;' % (type, self.name)] + else: + return ['extern %s _%s;' % (self.type[:-1], self.name), + '%s %s = (%s)&_%s;' % (type, self.name, type, self.name)] + class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name @@ -373,7 +381,9 @@ def get_type_for_declaration(self): return 'PyObject' - def get_struct_to_export(self, space, value): + def get_name_for_structnode(self): + return self.name + def get_value_for_structnode(self, space, value): from pypy.module.cpyext.pyobject import make_ref value = make_ref(space, value) return value._obj @@ -397,7 +407,9 @@ def get_type_for_declaration(self): return self.type - def get_value_to_export(self, space, value): + def get_name_for_structnode(self): + return '_' + self.name + def get_value_for_structnode(self, space, value): from pypy.module.cpyext.datetime import PyDateTime_CAPI struct = rffi.cast(lltype.Ptr(PyDateTime_CAPI), value)._obj @@ -420,7 +432,9 @@ def get_type_for_declaration(self): return 'PyObject*' - def get_value_to_export(self, space, value): + def get_name_for_structnode(self): + return '_' + self.name + def get_value_for_structnode(self, space, value): from pypy.module.cpyext.pyobject import make_ref from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj @@ -444,7 +458,9 @@ def get_type_for_declaration(self): return 'PyTypeObject' - def get_value_to_export(self, space, value): + def get_name_for_structnode(self): + return self.name + def get_value_for_structnode(self, space, value): from pypy.module.cpyext.pyobject import make_ref from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr return rffi.cast(PyTypeObjectPtr, make_ref(space, value))._obj @@ -863,13 +879,8 @@ # Generate definitions for global structures struct_file = udir.join('pypy_structs.c') structs = ["#include "] - for name, obj in GLOBALS.iteritems(): - type = obj.get_type_for_declaration() - if not obj.needs_hidden_global_structure: - structs.append('%s %s;' % (type, name)) - else: - structs.append('extern %s _%s;' % (obj.type[:-1], name)) - structs.append('%s %s = (%s)&_%s;' % (type, name, type, name)) + for obj in GLOBALS.values(): + structs.extend(obj.get_data_definition()) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -912,11 +923,9 @@ run_bootstrap_functions(space) # populate static data - for name, obj in GLOBALS.iteritems(): - if obj.needs_hidden_global_structure: - name = '_' + name - value = obj.eval(space) - struct = obj.get_value_to_export(space, value) + for obj in GLOBALS.values(): + name = obj.get_name_for_structnode() + struct = obj.get_value_for_structnode(space, obj.eval(space)) struct._compilation_info = eci export_struct(name, struct) From afa at codespeak.net Tue Jun 8 23:52:34 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 8 Jun 2010 23:52:34 +0200 (CEST) Subject: [pypy-svn] r75222 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608215234.03CB7282BDE@codespeak.net> Author: afa Date: Tue Jun 8 23:52:33 2010 New Revision: 75222 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Fix Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Tue Jun 8 23:52:33 2010 @@ -411,7 +411,7 @@ return '_' + self.name def get_value_for_structnode(self, space, value): from pypy.module.cpyext.datetime import PyDateTime_CAPI - struct = rffi.cast(lltype.Ptr(PyDateTime_CAPI), value)._obj + return rffi.cast(lltype.Ptr(PyDateTime_CAPI), value)._obj def set_value_in_ctypes_dll(self, space, dll, value): name = self.name.replace('Py', 'PyPy') From arigo at codespeak.net Wed Jun 9 00:02:01 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 00:02:01 +0200 (CEST) Subject: [pypy-svn] r75223 - in pypy/branch: blackhole-improvement blackhole-improvement-merge Message-ID: <20100608220201.04D58282BDE@codespeak.net> Author: arigo Date: Wed Jun 9 00:02:00 2010 New Revision: 75223 Removed: pypy/branch/blackhole-improvement/ pypy/branch/blackhole-improvement-merge/ Log: Remove merged branches. From afa at codespeak.net Wed Jun 9 00:22:05 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 00:22:05 +0200 (CEST) Subject: [pypy-svn] r75224 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608222205.0707D282BDE@codespeak.net> Author: afa Date: Wed Jun 9 00:22:03 2010 New Revision: 75224 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: more simplification Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 00:22:03 2010 @@ -369,6 +369,12 @@ return ['extern %s _%s;' % (self.type[:-1], self.name), '%s %s = (%s)&_%s;' % (type, self.name, type, self.name)] + def get_global_code_for_bridge(self): + if not self.needs_hidden_global_structure: + return [] + else: + return ['%s _%s;' % (self.type[:-1], self.name)] + class GlobalStaticPyObject(BaseGlobalObject): def __init__(self, name, expr): self.name = name @@ -376,8 +382,6 @@ self.expr = expr needs_hidden_global_structure = False - def get_global_code_for_bridge(self): - return [] def get_type_for_declaration(self): return 'PyObject' @@ -402,8 +406,6 @@ self.expr = expr needs_hidden_global_structure = True - def get_global_code_for_bridge(self): - return ['%s _%s;' % (self.type[:-1], self.name)] def get_type_for_declaration(self): return self.type @@ -427,8 +429,6 @@ % (exc_name,)) needs_hidden_global_structure = True - def get_global_code_for_bridge(self): - return ['%s _%s;' % (self.type[:-1], self.name)] def get_type_for_declaration(self): return 'PyObject*' @@ -453,8 +453,6 @@ self.expr = expr needs_hidden_global_structure = False - def get_global_code_for_bridge(self): - return [] def get_type_for_declaration(self): return 'PyTypeObject' From afa at codespeak.net Wed Jun 9 00:25:22 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 00:25:22 +0200 (CEST) Subject: [pypy-svn] r75225 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100608222522.94B14282BDE@codespeak.net> Author: afa Date: Wed Jun 9 00:25:21 2010 New Revision: 75225 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Rename objects in one place Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 00:25:21 2010 @@ -394,8 +394,7 @@ def set_value_in_ctypes_dll(self, space, dll, value): # it's a structure, get its adress - name = self.name.replace('Py', 'PyPy') - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, name) + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, self.name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) attach_and_track(space, py_obj, value) @@ -416,8 +415,7 @@ return rffi.cast(lltype.Ptr(PyDateTime_CAPI), value)._obj def set_value_in_ctypes_dll(self, space, dll, value): - name = self.name.replace('Py', 'PyPy') - ptr = ctypes.c_void_p.in_dll(dll, name) + ptr = ctypes.c_void_p.in_dll(dll, self.name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value @@ -441,8 +439,7 @@ def set_value_in_ctypes_dll(self, space, dll, value): # it's a pointer - name = self.name.replace('Py', 'PyPy') - in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(dll, name) + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(dll, self.name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) attach_and_track(space, py_obj, value) @@ -465,8 +462,7 @@ def set_value_in_ctypes_dll(self, space, dll, value): # it's a structure, get its adress - name = self.name.replace('Py', 'PyPy') - in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, name) + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(dll, self.name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) attach_and_track(space, py_obj, value) @@ -725,6 +721,8 @@ db = LowLevelDatabase() generate_macros(export_symbols, rename=True) + for obj in GLOBALS.values(): + obj.name = obj.name.replace('Py', 'PyPy') # Structure declaration code members = [] From afa at codespeak.net Wed Jun 9 01:38:54 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 01:38:54 +0200 (CEST) Subject: [pypy-svn] r75226 - in pypy/branch/cpyext-init-cleanup/pypy/module/cpyext: . include Message-ID: <20100608233854.B85FB282BDE@codespeak.net> Author: afa Date: Wed Jun 9 01:38:52 2010 New Revision: 75226 Added: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl (contents, props changed) pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/mysnprintf.h (contents, props changed) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/bufferobject.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/eval.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/modsupport.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/object.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pycobject.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pyerrors.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pythonrun.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/sliceobject.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/stringobject.h pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/tupleobject.h Log: Don't need to maintain a list of the functions implemented in C. Instead, they must be declared with the PyAPI_FUNC macro. Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 01:38:52 2010 @@ -306,28 +306,32 @@ INTERPLEVEL_API = {} FUNCTIONS = {} -SYMBOLS_C = [ - 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse', - 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords', - '_PyArg_NoKeywords', - 'PyString_FromFormat', 'PyString_FromFormatV', - 'PyModule_AddObject', 'PyModule_AddIntConstant', 'PyModule_AddStringConstant', - 'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack', - - 'PyErr_Format', 'PyErr_NewException', - - 'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction', - 'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs', - - 'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject', - 'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject', - - 'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr', - 'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr', - 'PyCObject_Type', 'init_pycobject', +SYMBOLS_C = [] + +def gather_PyAPI_symbols(): + import os, re + include_dir = py.path.local(__file__).dirpath() / 'include' + for filename in include_dir.listdir("*.h"): + for line in filename.open(): + if 'PyAPI_' not in line: + continue + if re.match('# *define', line): + continue + + match = re.match(r'PyAPI_FUNC\(.+?\)\s+(.+)\(', line) + if match: + name = match.group(1) + SYMBOLS_C.append(name) + continue + match = re.match(r'PyAPI_DATA\(.+?\)\s+(.+);', line) + if match: + name = match.group(1) + SYMBOLS_C.append(name) + continue + + assert False, "unknown PyAPI declaration: %r" % (line,) +gather_PyAPI_symbols() - 'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer', -] TYPES = {} GLOBALS = {} FORWARD_DECLS = [] @@ -469,6 +473,7 @@ GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') +GlobalStaticPyObject.declare('_Py_EllipsisObject', 'space.w_Ellipsis') GlobalStaticPyObject.declare('_Py_NotImplementedStruct', 'space.w_NotImplemented') GlobalStructurePointer.declare('PyDateTimeAPI', 'PyDateTime_CAPI*', Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/Python.h Wed Jun 9 01:38:52 2010 @@ -82,6 +82,7 @@ #include "funcobject.h" #include "modsupport.h" +#include "mysnprintf.h" #include "pythonrun.h" #include "pyerrors.h" #include "stringobject.h" @@ -104,6 +105,8 @@ #include +#include "complexobject.inl" + /* Define macros for inline documentation. */ #define PyDoc_VAR(name) static char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/bufferobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/bufferobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/bufferobject.h Wed Jun 9 01:38:52 2010 @@ -15,18 +15,18 @@ #define Py_END_OF_BUFFER (-1) -PyObject* PyBuffer_FromObject(PyObject *base, - Py_ssize_t offset, Py_ssize_t size); -PyObject* PyBuffer_FromReadWriteObject(PyObject *base, - Py_ssize_t offset, - Py_ssize_t size); +PyAPI_FUNC(PyObject*) PyBuffer_FromObject(PyObject *base, + Py_ssize_t offset, Py_ssize_t size); +PyAPI_FUNC(PyObject*) PyBuffer_FromReadWriteObject(PyObject *base, + Py_ssize_t offset, + Py_ssize_t size); -PyObject* PyBuffer_FromMemory(void *ptr, Py_ssize_t size); -PyObject* PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size); +PyAPI_FUNC(PyObject*) PyBuffer_FromMemory(void *ptr, Py_ssize_t size); +PyAPI_FUNC(PyObject*) PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size); -PyObject* PyBuffer_New(Py_ssize_t size); +PyAPI_FUNC(PyObject*) PyBuffer_New(Py_ssize_t size); -void init_bufferobject(void); +PyAPI_FUNC(void) init_bufferobject(void); #ifdef __cplusplus } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.h Wed Jun 9 01:38:52 2010 @@ -11,16 +11,6 @@ double imag; } Py_complex; -/* generated function */ -PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *); - -Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj) -{ - Py_complex result; - _PyComplex_AsCComplex(obj, &result); - return result; -} - #ifdef __cplusplus } #endif Added: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl ============================================================================== --- (empty file) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl Wed Jun 9 01:38:52 2010 @@ -0,0 +1,20 @@ +/* Complex object inline functions */ + +#ifndef Py_COMPLEXOBJECT_INL +#define Py_COMPLEXOBJECT_INL +#ifdef __cplusplus +extern "C" { +#endif + +Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj) +{ + Py_complex result; + _PyComplex_AsCComplex(obj, &result); + return result; +} + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_COMPLEXOBJECT_INL */ Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/datetime.h Wed Jun 9 01:38:52 2010 @@ -13,7 +13,6 @@ PyTypeObject *DeltaType; } PyDateTime_CAPI; -PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; #define PyDateTime_IMPORT _PyDateTime_Import() typedef struct { Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/eval.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/eval.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/eval.h Wed Jun 9 01:38:52 2010 @@ -12,12 +12,12 @@ #define PyEval_CallObject(func,arg) \ PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL) -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_CallFunctionObjArgs(PyObject *callable, ...); -PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...); +PyAPI_FUNC(PyObject *) PyEval_CallFunction(PyObject *obj, const char *format, ...); +PyAPI_FUNC(PyObject *) PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...); +PyAPI_FUNC(PyObject *) PyObject_CallFunction(PyObject *obj, char *format, ...); +PyAPI_FUNC(PyObject *) PyObject_CallMethod(PyObject *obj, char *name, char *format, ...); +PyAPI_FUNC(PyObject *) PyObject_CallFunctionObjArgs(PyObject *callable, ...); +PyAPI_FUNC(PyObject *) PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...); /* These constants are also defined in cpyext/eval.py */ #define Py_single_input 256 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/modsupport.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/modsupport.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/modsupport.h Wed Jun 9 01:38:52 2010 @@ -10,33 +10,35 @@ #define PYTHON_API_VERSION 1013 #define PYTHON_API_STRING "1013" -int PyArg_Parse(PyObject *, const char *, ...); -int PyArg_ParseTuple(PyObject *, const char *, ...); -int PyArg_VaParse(PyObject *, const char *, va_list); - -int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); -int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); +PyAPI_FUNC(int) PyArg_Parse(PyObject *, const char *, ...); +PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); +PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list); + +PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, ...); +PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, va_list); #define Py_InitModule(name, methods) \ - Py_InitModule4(name, methods, (char *)NULL, (PyObject *)NULL, \ - PYTHON_API_VERSION) + Py_InitModule4(name, methods, (char *)NULL, (PyObject *)NULL, \ + PYTHON_API_VERSION) #define Py_InitModule3(name, methods, doc) \ - Py_InitModule4(name, methods, doc, (PyObject *)NULL, \ - PYTHON_API_VERSION) + Py_InitModule4(name, methods, doc, (PyObject *)NULL, \ + PYTHON_API_VERSION) -int PyModule_AddObject(PyObject *m, const char *name, PyObject *o); -int PyModule_AddIntConstant(PyObject *m, const char *name, long value); -int PyModule_AddStringConstant(PyObject *m, const char *name, const char *value); +PyAPI_FUNC(int) PyModule_AddObject(PyObject *m, const char *name, PyObject *o); +PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *m, const char *name, long value); +PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *m, const char *name, const char *value); -PyObject * Py_BuildValue(const char *, ...); -PyObject * _Py_BuildValue_SizeT(const char *, ...); -int _PyArg_NoKeywords(const char *funcname, PyObject *kw); +PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); +PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); +PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list va); +PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list va); +PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kw); -int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...); +PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...); /* * This is from pyport.h. Perhaps it belongs elsewhere. Added: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/mysnprintf.h ============================================================================== --- (empty file) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/mysnprintf.h Wed Jun 9 01:38:52 2010 @@ -0,0 +1,13 @@ +#ifndef Py_MYSNPRINTF_H +#define Py_MYSNPRINTF_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char *format, ...); +PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va); + +#ifdef __cplusplus +} +#endif +#endif Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/object.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/object.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/object.h Wed Jun 9 01:38:52 2010 @@ -479,13 +479,12 @@ ((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp))) /* Copied from CPython ----------------------------- */ -int PyObject_AsReadBuffer(PyObject *, const void **, Py_ssize_t *); -int PyObject_AsWriteBuffer(PyObject *, void **, Py_ssize_t *); -int PyObject_CheckReadBuffer(PyObject *); +PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *, const void **, Py_ssize_t *); +PyAPI_FUNC(int) PyObject_AsWriteBuffer(PyObject *, void **, Py_ssize_t *); +PyAPI_FUNC(int) PyObject_CheckReadBuffer(PyObject *); /* PyPy internal ----------------------------------- */ -int PyPyType_Register(PyTypeObject *); #define PyObject_Length PyObject_Size #define _PyObject_GC_Del PyObject_GC_Del Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pycobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pycobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pycobject.h Wed Jun 9 01:38:52 2010 @@ -47,7 +47,9 @@ void (*destructor)(void *); } PyCObject; #endif - + +PyAPI_FUNC(void) init_pycobject(void); + #ifdef __cplusplus } #endif Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pyerrors.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pyerrors.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pyerrors.h Wed Jun 9 01:38:52 2010 @@ -7,8 +7,8 @@ extern "C" { #endif -PyObject *PyErr_NewException(char *name, PyObject *base, PyObject *dict); -PyObject *PyErr_Format(PyObject *exception, const char *format, ...); +PyAPI_FUNC(PyObject *) PyErr_NewException(char *name, PyObject *base, PyObject *dict); +PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *exception, const char *format, ...); #ifdef __cplusplus } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pythonrun.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pythonrun.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/pythonrun.h Wed Jun 9 01:38:52 2010 @@ -6,7 +6,7 @@ extern "C" { #endif - void Py_FatalError(const char *msg); +PyAPI_FUNC(void) Py_FatalError(const char *msg); #ifdef __cplusplus } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/sliceobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/sliceobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/sliceobject.h Wed Jun 9 01:38:52 2010 @@ -5,9 +5,6 @@ #endif /* The unique ellipsis object "..." */ - -PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */ - #define Py_Ellipsis (&_Py_EllipsisObject) typedef struct { Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/stringobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/stringobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/stringobject.h Wed Jun 9 01:38:52 2010 @@ -18,8 +18,8 @@ Py_ssize_t size; } PyStringObject; -PyObject *PyString_FromFormatV(const char *format, va_list vargs); -PyObject *PyString_FromFormat(const char *format, ...); +PyAPI_FUNC(PyObject *) PyString_FromFormatV(const char *format, va_list vargs); +PyAPI_FUNC(PyObject *) PyString_FromFormat(const char *format, ...); #ifdef __cplusplus } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/tupleobject.h ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/tupleobject.h (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/tupleobject.h Wed Jun 9 01:38:52 2010 @@ -8,7 +8,7 @@ #endif /* defined in varargswrapper.c */ -PyObject * PyTuple_Pack(Py_ssize_t, ...); +PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); #define PyTuple_SET_ITEM PyTuple_SetItem #define PyTuple_GET_ITEM PyTuple_GetItem From afa at codespeak.net Wed Jun 9 01:51:40 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 01:51:40 +0200 (CEST) Subject: [pypy-svn] r75227 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include Message-ID: <20100608235140.3BCF4282BDE@codespeak.net> Author: afa Date: Wed Jun 9 01:51:38 2010 New Revision: 75227 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl Log: kill a compilation warning Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/include/complexobject.inl Wed Jun 9 01:51:38 2010 @@ -6,6 +6,9 @@ extern "C" { #endif +/* generated function */ +PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *); + Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj) { Py_complex result; From afa at codespeak.net Wed Jun 9 09:52:07 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 09:52:07 +0200 (CEST) Subject: [pypy-svn] r75228 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100609075207.7AF36282BDE@codespeak.net> Author: afa Date: Wed Jun 9 09:52:05 2010 New Revision: 75228 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Move module-level code to a function more simplifications Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 09:52:05 2010 @@ -21,6 +21,7 @@ from pypy.interpreter.nestedscope import Cell from pypy.interpreter.module import Module from pypy.interpreter.function import StaticMethod +from pypy.interpreter.typedef import TypeDef from pypy.objspace.std.sliceobject import W_SliceObject from pypy.module.__builtin__.descriptor import W_Property from pypy.rlib.entrypoint import entrypoint @@ -453,6 +454,14 @@ self.type = 'PyTypeObject*' self.expr = expr + def eval(self, space): + if isinstance(self.expr, str): + return BaseGlobalObject.eval(self, space) + elif isinstance(self.expr, TypeDef): + return space.gettypeobject(self.expr) + else: + raise ValueError, "Unknonwn expression: %r" % (self.expr) + needs_hidden_global_structure = False def get_type_for_declaration(self): return 'PyTypeObject' @@ -470,50 +479,49 @@ py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) attach_and_track(space, py_obj, value) -GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') -GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') -GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') -GlobalStaticPyObject.declare('_Py_EllipsisObject', 'space.w_Ellipsis') -GlobalStaticPyObject.declare('_Py_NotImplementedStruct', - 'space.w_NotImplemented') -GlobalStructurePointer.declare('PyDateTimeAPI', 'PyDateTime_CAPI*', - 'cpyext.datetime.build_datetime_api(space)') - def build_exported_objects(): # Standard exceptions for exc_name in exceptions.Module.interpleveldefs.keys(): GlobalExceptionPointer.declare(exc_name) + # Global object structures + GlobalStaticPyObject.declare('_Py_NoneStruct', 'space.w_None') + GlobalStaticPyObject.declare('_Py_TrueStruct', 'space.w_True') + GlobalStaticPyObject.declare('_Py_ZeroStruct', 'space.w_False') + GlobalStaticPyObject.declare('_Py_EllipsisObject', 'space.w_Ellipsis') + GlobalStaticPyObject.declare('_Py_NotImplementedStruct', + 'space.w_NotImplemented') + + GlobalStructurePointer.declare('PyDateTimeAPI', 'PyDateTime_CAPI*', + 'cpyext.datetime.build_datetime_api(space)') + # Common types with their own struct - for cpyname, pypyexpr in { - "Type": "space.w_type", - "String": "space.w_str", - "Unicode": "space.w_unicode", - "BaseString": "space.w_basestring", - "Dict": "space.w_dict", - "Tuple": "space.w_tuple", - "List": "space.w_list", - "Int": "space.w_int", - "Bool": "space.w_bool", - "Float": "space.w_float", - "Long": "space.w_long", - "Complex": "space.w_complex", - "BaseObject": "space.w_object", - 'None': 'space.type(space.w_None)', - 'NotImplemented': 'space.type(space.w_NotImplemented)', - 'Cell': 'space.gettypeobject(Cell.typedef)', - 'Module': 'space.gettypeobject(Module.typedef)', - 'Property': 'space.gettypeobject(W_Property.typedef)', - 'Slice': 'space.gettypeobject(W_SliceObject.typedef)', - 'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)', - 'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)', - }.items(): - GlobalTypeObject.declare(cpyname, pypyexpr) + GlobalTypeObject.declare("Type", "space.w_type") + GlobalTypeObject.declare("String", "space.w_str") + GlobalTypeObject.declare("Unicode", "space.w_unicode") + GlobalTypeObject.declare("BaseString", "space.w_basestring") + GlobalTypeObject.declare("Dict", "space.w_dict") + GlobalTypeObject.declare("Tuple", "space.w_tuple") + GlobalTypeObject.declare("List", "space.w_list") + GlobalTypeObject.declare("Int", "space.w_int") + GlobalTypeObject.declare("Bool", "space.w_bool") + GlobalTypeObject.declare("Float", "space.w_float") + GlobalTypeObject.declare("Long", "space.w_long") + GlobalTypeObject.declare("Complex", "space.w_complex") + GlobalTypeObject.declare("BaseObject", "space.w_object") + GlobalTypeObject.declare("None", "space.type(space.w_None)") + GlobalTypeObject.declare("NotImplemented", "space.type(space.w_NotImplemented)") + GlobalTypeObject.declare("Cell", Cell.typedef) + GlobalTypeObject.declare("Module", Module.typedef) + GlobalTypeObject.declare("Property", W_Property.typedef) + GlobalTypeObject.declare("Slice", W_SliceObject.typedef) + GlobalTypeObject.declare("StaticMethod", StaticMethod.typedef) + from pypy.module.cpyext.methodobject import W_PyCFunctionObject + GlobalTypeObject.declare("CFunction", W_PyCFunctionObject.typedef) for cpyname in 'Method List Int Long Dict Tuple Class'.split(): FORWARD_DECLS.append('typedef struct { PyObject_HEAD } ' 'Py%sObject' % (cpyname, )) -build_exported_objects() PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) @@ -719,7 +727,7 @@ # Do not call this more than once per process def build_bridge(space): "NOT_RPYTHON" - from pypy.module.cpyext.pyobject import make_ref + build_exported_objects() export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from pypy.translator.c.database import LowLevelDatabase @@ -908,7 +916,7 @@ def setup_library(space): "NOT_RPYTHON" - from pypy.module.cpyext.pyobject import make_ref + build_exported_objects() export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from pypy.translator.c.database import LowLevelDatabase From arigo at codespeak.net Wed Jun 9 10:34:02 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 10:34:02 +0200 (CEST) Subject: [pypy-svn] r75229 - in pypy/trunk/pypy/jit: backend/llgraph backend/x86 metainterp metainterp/test tool tool/test Message-ID: <20100609083402.E5296282BDE@codespeak.net> Author: arigo Date: Wed Jun 9 10:34:00 2010 New Revision: 75229 Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/metainterp/executor.py pypy/trunk/pypy/jit/metainterp/jitprof.py pypy/trunk/pypy/jit/metainterp/optimizeopt.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/resoperation.py pypy/trunk/pypy/jit/metainterp/simple_optimize.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py pypy/trunk/pypy/jit/metainterp/test/test_string.py pypy/trunk/pypy/jit/tool/jitoutput.py pypy/trunk/pypy/jit/tool/test/test_jitoutput.py Log: issue545 testing Change CALL_PURE into a temporary operation. The idea is to fix issue545 by preventing multiple calls to a pure function. Now a call to a pure function is traced as a normal CALL, then immediately turned into a CALL_PURE by whacking at the history, and the value that it returned is inserted as first argument. If optimizeopt can constant-fold it away, it thus has the returned value available. If it cannot, then it will turn it again into a regular CALL. Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py Wed Jun 9 10:34:00 2010 @@ -127,7 +127,6 @@ 'arraylen_gc' : (('ref',), 'int'), 'call' : (('ref', 'varargs'), 'intorptr'), 'call_assembler' : (('ref', 'varargs'), 'intorptr'), - 'call_pure' : (('ref', 'varargs'), 'intorptr'), 'cond_call_gc_wb' : (('ptr', 'ptr'), None), 'oosend' : (('varargs',), 'intorptr'), 'oosend_pure' : (('varargs',), 'intorptr'), @@ -787,8 +786,6 @@ FLOAT: 0.0} return d[calldescr.typeinfo] - op_call_pure = op_call - def op_cond_call_gc_wb(self, descr, a, b): py.test.skip("cond_call_gc_wb not supported") @@ -925,8 +922,6 @@ return ootype.cast_to_object(res) return res - op_call_pure = op_call - def op_oosend(self, descr, obj, *args): METH = descr.METH obj = ootype.cast_from_object(descr.SELFTYPE, obj) Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Wed Jun 9 10:34:00 2010 @@ -1346,8 +1346,6 @@ self.mc.AND(eax, imm(0xff)) elif size == 2: self.mc.AND(eax, imm(0xffff)) - - genop_call_pure = genop_call def genop_guard_call_may_force(self, op, guard_op, addr, arglocs, result_loc): Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Wed Jun 9 10:34:00 2010 @@ -630,7 +630,6 @@ def consider_call(self, op): self._consider_call(op) - consider_call_pure = consider_call def consider_call_may_force(self, op, guard_op): assert guard_op is not None Modified: pypy/trunk/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/executor.py Wed Jun 9 10:34:00 2010 @@ -15,7 +15,8 @@ # ____________________________________________________________ -def _prepare_call(argboxes, descr): +def do_call(cpu, metainterp, argboxes, descr): + assert metainterp is not None # count the number of arguments of the different types count_i = count_r = count_f = 0 for i in range(1, len(argboxes)): @@ -47,11 +48,6 @@ func = argboxes[0].getint() # do the call using the correct function from the cpu rettype = descr.get_return_type() - return func, args_i, args_r, args_f, rettype - -def do_call(cpu, metainterp, argboxes, descr): - assert metainterp is not None - func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) if rettype == INT: try: result = cpu.bh_call_i(func, descr, args_i, args_r, args_f) @@ -84,21 +80,6 @@ do_call_loopinvariant = do_call do_call_may_force = do_call -def do_call_pure(cpu, _, argboxes, descr): - # this version does not deal with exceptions at all - # xxx in case of MemoryError, it crashes the JIT - func, args_i, args_r, args_f, rettype = _prepare_call(argboxes, descr) - if rettype == INT: - return BoxInt(cpu.bh_call_i(func, descr, args_i, args_r, args_f)) - if rettype == REF: - return BoxPtr(cpu.bh_call_r(func, descr, args_i, args_r, args_f)) - if rettype == FLOAT: - return BoxFloat(cpu.bh_call_f(func, descr, args_i, args_r, args_f)) - if rettype == VOID: - cpu.bh_call_v(func, descr, args_i, args_r, args_f) - return None - raise AssertionError("bad rettype") - def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): array = arraybox.getref_base() index = indexbox.getint() Modified: pypy/trunk/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/jitprof.py (original) +++ pypy/trunk/pypy/jit/metainterp/jitprof.py Wed Jun 9 10:34:00 2010 @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 4 # one for TOTAL, 4 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 1 # one for TOTAL, 1 for calls, update if needed class BaseProfiler(object): pass @@ -88,7 +88,7 @@ t1 = 0 times = None counters = None - calls = None + calls = 0 current = None printing = True @@ -97,7 +97,7 @@ self.t1 = self.starttime self.times = [0, 0] self.counters = [0] * ncounters - self.calls = [[0, 0], [0, 0]] + self.calls = 0 self.current = [] def finish(self): @@ -150,10 +150,8 @@ def count_ops(self, opnum, kind=OPS): from pypy.jit.metainterp.resoperation import rop self.counters[kind] += 1 - if opnum == rop.CALL: # or opnum == rop.OOSEND: - self.calls[kind-OPS][0] += 1 - elif opnum == rop.CALL_PURE: # or opnum == rop.OOSEND_PURE: - self.calls[kind-OPS][1] += 1 + if opnum == rop.CALL and kind == RECORDED_OPS:# or opnum == rop.OOSEND: + self.calls += 1 def print_stats(self): cnt = self.counters @@ -166,11 +164,8 @@ line = "TOTAL: \t\t%f\n" % (self.tk - self.starttime, ) os.write(2, line) self._print_intline("ops", cnt[OPS]) - self._print_intline(" calls", calls[0][0]) - self._print_intline(" pure calls", calls[0][1]) self._print_intline("recorded ops", cnt[RECORDED_OPS]) - self._print_intline(" calls", calls[1][0]) - self._print_intline(" pure calls", calls[1][1]) + self._print_intline(" calls", calls) self._print_intline("guards", cnt[GUARDS]) self._print_intline("opt ops", cnt[OPT_OPS]) self._print_intline("opt guards", cnt[OPT_GUARDS]) Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py Wed Jun 9 10:34:00 2010 @@ -960,6 +960,18 @@ resvalue = self.getvalue(op.result) self.loop_invariant_results[key] = resvalue + def optimize_CALL_PURE(self, op): + for arg in op.args: + if self.get_constant_box(arg) is None: + break + else: + # all constant arguments: constant-fold away + self.make_constant(op.result, op.args[0]) + return + # replace CALL_PURE with just CALL + self.emit_operation(ResOperation(rop.CALL, op.args[1:], op.result, + op.descr)) + def optimize_INT_AND(self, op): v1 = self.getvalue(op.args[0]) v2 = self.getvalue(op.args[1]) @@ -1071,7 +1083,7 @@ return None def emitting_operation(self, op): - if op.opnum != rop.CALL_PURE and op.has_no_side_effect(): + if op.has_no_side_effect(): return if op.is_ovf(): return @@ -1082,9 +1094,9 @@ opnum == rop.SETARRAYITEM_GC or opnum == rop.DEBUG_MERGE_POINT): return + assert opnum != rop.CALL_PURE if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or - opnum == rop.CALL_PURE or opnum == rop.CALL_ASSEMBLER): if opnum == rop.CALL_ASSEMBLER: effectinfo = None Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Wed Jun 9 10:34:00 2010 @@ -1054,8 +1054,8 @@ if effect == effectinfo.EF_CANNOT_RAISE: return self.execute_varargs(rop.CALL, allboxes, descr, False) elif effect == effectinfo.EF_PURE: - return self.execute_varargs(rop.CALL_PURE, allboxes, - descr, False) + return self.metainterp.record_result_of_call_pure( + self.execute_varargs(rop.CALL, allboxes, descr, False)) elif effect == effectinfo.EF_LOOPINVARIANT: return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes, descr, True) @@ -2019,6 +2019,26 @@ max_key = key return max_key + def record_result_of_call_pure(self, resbox): + """ Patch a CALL into a CALL_PURE. + """ + op = self.history.operations[-1] + assert op.opnum == rop.CALL + resbox_as_const = resbox.constbox() + for arg in op.args: + if not isinstance(arg, Const): + break + else: + # all-constants: remove the CALL operation now and propagate a + # constant result + self.history.operations.pop() + return resbox_as_const + # not all constants (so far): turn CALL into CALL_PURE, which might + # be either removed later by optimizeopt or turned back into CALL. + op.opnum = rop.CALL_PURE + op.args = [resbox_as_const] + op.args + return resbox + def direct_assembler_call(self, token): """ Generate a direct call to assembler for portal entry point, patching the CALL_MAY_FORCE that occurred just now. Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resoperation.py (original) +++ pypy/trunk/pypy/jit/metainterp/resoperation.py Wed Jun 9 10:34:00 2010 @@ -135,9 +135,6 @@ '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations ----- '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations ----- - #'OOSEND_PURE', # ootype operation - 'CALL_PURE', - # 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', @@ -231,6 +228,9 @@ 'CALL_MAY_FORCE', 'CALL_LOOPINVARIANT', #'OOSEND', # ootype operation + #'OOSEND_PURE', # ootype operation + 'CALL_PURE', # removed before it's passed to the backend + # CALL_PURE(result, func, arg_1,..,arg_n) '_CANRAISE_LAST', # ----- end of can_raise operations ----- '_OVF_FIRST', # ----- start of is_ovf operations ----- Modified: pypy/trunk/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/trunk/pypy/jit/metainterp/simple_optimize.py Wed Jun 9 10:34:00 2010 @@ -15,6 +15,8 @@ descr = op.args[0] assert isinstance(descr, AbstractDescr) op = ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) + elif op.opnum == rop.CALL_PURE: + op = ResOperation(rop.CALL, op.args[1:], op.result, op.descr) elif op.opnum == rop.VIRTUAL_REF: op = ResOperation(rop.SAME_AS, [op.args[0]], op.result) elif op.opnum == rop.VIRTUAL_REF_FINISH: Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Wed Jun 9 10:34:00 2010 @@ -364,7 +364,38 @@ return externfn(n, n+1) res = self.interp_operations(f, [6]) assert res == 42 - self.check_operations_history(int_add=0, int_mul=0, call=0) + # CALL_PURE is not recorded in the history if all-constant args + self.check_operations_history(int_add=0, int_mul=0, + call=0, call_pure=0) + + def test_residual_call_pure_1(self): + def externfn(x, y): + return x * y + externfn._pure_function_ = True + def f(n): + return externfn(n, n+1) + res = self.interp_operations(f, [6]) + assert res == 42 + # CALL_PURE is recorded in the history if not-all-constant args + self.check_operations_history(int_add=1, int_mul=0, + call=0, call_pure=1) + + def test_residual_call_pure_2(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + def externfn(x): + return x - 1 + externfn._pure_function_ = True + def f(n): + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + n = externfn(n) + return n + res = self.meta_interp(f, [7]) + assert res == 0 + # CALL_PURE is recorded in the history, but turned into a CALL + # by optimizeopt.py + self.check_loops(int_sub=0, call=1, call_pure=0) def test_constfold_call_pure(self): myjitdriver = JitDriver(greens = ['m'], reds = ['n']) @@ -379,6 +410,8 @@ return n res = self.meta_interp(f, [21, 5]) assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) def test_constfold_call_pure_2(self): myjitdriver = JitDriver(greens = ['m'], reds = ['n']) @@ -397,6 +430,8 @@ return n res = self.meta_interp(f, [21, 5]) assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) Modified: pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_jitprof.py Wed Jun 9 10:34:00 2010 @@ -84,8 +84,7 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded) x (inpure, pure) - assert profiler.calls == [[1, 0], [1, 0]] + assert profiler.calls == 1 def test_blackhole_pure(self): @purefunction @@ -105,5 +104,4 @@ res = self.meta_interp(f, [6, 7, 2]) assert res == f(6, 7, 2) profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded) x (inpure, pure) - assert profiler.calls == [[0, 1], [0, 0]] + assert profiler.calls == 1 Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Wed Jun 9 10:34:00 2010 @@ -2611,11 +2611,41 @@ ops = ''' [p1, i1] setfield_gc(p1, i1, descr=valuedescr) - i3 = call_pure(p1, descr=plaincalldescr) + i3 = call_pure(42, p1, descr=plaincalldescr) setfield_gc(p1, i3, descr=valuedescr) jump(p1, i3) ''' - self.optimize_loop(ops, 'Not, Not', ops) + expected = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call(p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + self.optimize_loop(ops, 'Not, Not', expected) + + def test_call_pure_constant_folding(self): + # CALL_PURE is not marked as is_always_pure(), because it is wrong + # to call the function arbitrary many times at arbitrary points in + # time. Check that it is either constant-folded (and replaced by + # the result of the call, recorded as the first arg), or turned into + # a regular CALL. + ops = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i3 = call_pure(42, 123456, 4, 5, 6, descr=plaincalldescr) + i4 = call_pure(43, 123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, i3, i4) + ''' + expected = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i4 = call(123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, 42, i4) + ''' + self.optimize_loop(ops, 'Not, Not, Not', expected) def test_vref_nonvirtual_nonescape(self): ops = """ Modified: pypy/trunk/pypy/jit/metainterp/test/test_string.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_string.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_string.py Wed Jun 9 10:34:00 2010 @@ -23,7 +23,7 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 1}) + self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0}) def test_eq_folded(self): jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i']) @@ -42,7 +42,7 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 0}) + self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0}) def test_newstr(self): jitdriver = JitDriver(greens = [], reds = ['n', 'm']) @@ -73,7 +73,9 @@ assert res == 6 class TestOOtype(StringTests, OOJitMixin): + CALL = "oosend" CALL_PURE = "oosend_pure" class TestLLtype(StringTests, LLJitMixin): + CALL = "call" CALL_PURE = "call_pure" Modified: pypy/trunk/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/trunk/pypy/jit/tool/jitoutput.py (original) +++ pypy/trunk/pypy/jit/tool/jitoutput.py Wed Jun 9 10:34:00 2010 @@ -15,11 +15,8 @@ '^Blackhole:\s+([\d.]+)$'), (None, '^TOTAL.*$'), (('ops.total',), '^ops:\s+(\d+)$'), - (('ops.calls',), '^\s+calls:\s+(\d+)$'), - (('ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('recorded_ops.total',), '^recorded ops:\s+(\d+)$'), (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), - (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), @@ -34,8 +31,9 @@ class Ops(object): total = 0 + +class RecordedOps(Ops): calls = 0 - pure_calls = 0 class Aborts(object): trace_too_long = 0 @@ -59,7 +57,7 @@ def __init__(self): self.ops = Ops() - self.recorded_ops = Ops() + self.recorded_ops = RecordedOps() self.abort = Aborts() def parse_prof(output): Modified: pypy/trunk/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/trunk/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/trunk/pypy/jit/tool/test/test_jitoutput.py Wed Jun 9 10:34:00 2010 @@ -35,11 +35,8 @@ assert info.blackhole_no == 1 assert info.backend_no == 1 assert info.ops.total == 2 - assert info.ops.calls == 0 - assert info.ops.pure_calls == 0 assert info.recorded_ops.total == 2 assert info.recorded_ops.calls == 0 - assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 assert info.opt_ops == 6 assert info.opt_guards == 1 @@ -51,11 +48,8 @@ Blackhole: 1 TOTAL: 0.025532 ops: 2 - calls: 1 - pure calls: 1 recorded ops: 6 calls: 3 - pure calls: 2 guards: 1 opt ops: 6 opt guards: 1 @@ -77,11 +71,8 @@ assert info.backend_no == 1 assert info.backend_time == 0.000525 assert info.ops.total == 2 - assert info.ops.calls == 1 - assert info.ops.pure_calls == 1 assert info.recorded_ops.total == 6 assert info.recorded_ops.calls == 3 - assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 assert info.opt_ops == 6 assert info.opt_guards == 1 From arigo at codespeak.net Wed Jun 9 11:38:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 11:38:44 +0200 (CEST) Subject: [pypy-svn] r75230 - pypy/trunk/pypy/lib/test2 Message-ID: <20100609093844.AB382282BDE@codespeak.net> Author: arigo Date: Wed Jun 9 11:38:42 2010 New Revision: 75230 Modified: pypy/trunk/pypy/lib/test2/test_dbm_extra.py Log: Missing import. Modified: pypy/trunk/pypy/lib/test2/test_dbm_extra.py ============================================================================== --- pypy/trunk/pypy/lib/test2/test_dbm_extra.py (original) +++ pypy/trunk/pypy/lib/test2/test_dbm_extra.py Wed Jun 9 11:38:42 2010 @@ -1,3 +1,5 @@ +import py + try: from pypy.lib import dbm except ImportError: From arigo at codespeak.net Wed Jun 9 12:07:03 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 12:07:03 +0200 (CEST) Subject: [pypy-svn] r75231 - in pypy/trunk/pypy/jit/tl/tinyframe: . test Message-ID: <20100609100703.92FAE282BFA@codespeak.net> Author: arigo Date: Wed Jun 9 12:07:02 2010 New Revision: 75231 Modified: pypy/trunk/pypy/jit/tl/tinyframe/ (props changed) pypy/trunk/pypy/jit/tl/tinyframe/test/ (props changed) Log: fixeol From arigo at codespeak.net Wed Jun 9 12:07:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 12:07:44 +0200 (CEST) Subject: [pypy-svn] r75232 - in pypy/trunk/py: . _cmdline _code _compat _io _log _path _path/gateway _plugin _process _test Message-ID: <20100609100744.A95AE282BFA@codespeak.net> Author: arigo Date: Wed Jun 9 12:07:42 2010 New Revision: 75232 Modified: pypy/trunk/py/ (props changed) pypy/trunk/py/__init__.py (props changed) pypy/trunk/py/__metainfo.py (props changed) pypy/trunk/py/_builtin.py (props changed) pypy/trunk/py/_cmdline/ (props changed) pypy/trunk/py/_cmdline/__init__.py (props changed) pypy/trunk/py/_cmdline/pycleanup.py (props changed) pypy/trunk/py/_cmdline/pyconvert_unittest.py (props changed) pypy/trunk/py/_cmdline/pycountloc.py (props changed) pypy/trunk/py/_cmdline/pylookup.py (props changed) pypy/trunk/py/_cmdline/pysvnwcrevert.py (props changed) pypy/trunk/py/_cmdline/pytest.py (props changed) pypy/trunk/py/_cmdline/pywhich.py (props changed) pypy/trunk/py/_code/ (props changed) pypy/trunk/py/_code/__init__.py (props changed) pypy/trunk/py/_code/_assertionnew.py (props changed) pypy/trunk/py/_code/_assertionold.py (props changed) pypy/trunk/py/_code/assertion.py (props changed) pypy/trunk/py/_code/code.py (props changed) pypy/trunk/py/_code/oldmagic.py (props changed) pypy/trunk/py/_code/oldmagic2.py (props changed) pypy/trunk/py/_code/source.py (props changed) pypy/trunk/py/_compat/ (props changed) pypy/trunk/py/_compat/__init__.py (props changed) pypy/trunk/py/_compat/dep_doctest.py (props changed) pypy/trunk/py/_compat/dep_optparse.py (props changed) pypy/trunk/py/_compat/dep_subprocess.py (props changed) pypy/trunk/py/_compat/dep_textwrap.py (props changed) pypy/trunk/py/_error.py (props changed) pypy/trunk/py/_io/ (props changed) pypy/trunk/py/_io/__init__.py (props changed) pypy/trunk/py/_io/capture.py (props changed) pypy/trunk/py/_io/saferepr.py (props changed) pypy/trunk/py/_io/terminalwriter.py (props changed) pypy/trunk/py/_log/ (props changed) pypy/trunk/py/_log/__init__.py (props changed) pypy/trunk/py/_log/log.py (props changed) pypy/trunk/py/_log/warning.py (props changed) pypy/trunk/py/_path/ (props changed) pypy/trunk/py/_path/__init__.py (props changed) pypy/trunk/py/_path/cacheutil.py (props changed) pypy/trunk/py/_path/common.py (props changed) pypy/trunk/py/_path/gateway/ (props changed) pypy/trunk/py/_path/gateway/__init__.py (props changed) pypy/trunk/py/_path/gateway/channeltest.py (props changed) pypy/trunk/py/_path/gateway/channeltest2.py (props changed) pypy/trunk/py/_path/gateway/remotepath.py (props changed) pypy/trunk/py/_path/local.py (props changed) pypy/trunk/py/_path/svnurl.py (props changed) pypy/trunk/py/_path/svnwc.py (props changed) pypy/trunk/py/_plugin/ (props changed) pypy/trunk/py/_plugin/__init__.py (props changed) pypy/trunk/py/_plugin/hookspec.py (props changed) pypy/trunk/py/_plugin/pytest__pytest.py (props changed) pypy/trunk/py/_plugin/pytest_assertion.py (props changed) pypy/trunk/py/_plugin/pytest_capture.py (props changed) pypy/trunk/py/_plugin/pytest_default.py (props changed) pypy/trunk/py/_plugin/pytest_doctest.py (props changed) pypy/trunk/py/_plugin/pytest_genscript.py (props changed) pypy/trunk/py/_plugin/pytest_helpconfig.py (props changed) pypy/trunk/py/_plugin/pytest_hooklog.py (props changed) pypy/trunk/py/_plugin/pytest_junitxml.py (props changed) pypy/trunk/py/_plugin/pytest_mark.py (props changed) pypy/trunk/py/_plugin/pytest_monkeypatch.py (props changed) pypy/trunk/py/_plugin/pytest_nose.py (props changed) pypy/trunk/py/_plugin/pytest_pastebin.py (props changed) pypy/trunk/py/_plugin/pytest_pdb.py (props changed) pypy/trunk/py/_plugin/pytest_pylint.py (props changed) pypy/trunk/py/_plugin/pytest_pytester.py (props changed) pypy/trunk/py/_plugin/pytest_recwarn.py (props changed) pypy/trunk/py/_plugin/pytest_restdoc.py (props changed) pypy/trunk/py/_plugin/pytest_resultlog.py (props changed) pypy/trunk/py/_plugin/pytest_runner.py (props changed) pypy/trunk/py/_plugin/pytest_skipping.py (props changed) pypy/trunk/py/_plugin/pytest_terminal.py (props changed) pypy/trunk/py/_plugin/pytest_tmpdir.py (props changed) pypy/trunk/py/_plugin/pytest_unittest.py (props changed) pypy/trunk/py/_plugin/standalonetemplate.py (props changed) pypy/trunk/py/_process/ (props changed) pypy/trunk/py/_process/__init__.py (props changed) pypy/trunk/py/_process/cmdexec.py (props changed) pypy/trunk/py/_process/forkedfunc.py (props changed) pypy/trunk/py/_process/killproc.py (props changed) pypy/trunk/py/_std.py (props changed) pypy/trunk/py/_test/ (props changed) pypy/trunk/py/_test/__init__.py (props changed) pypy/trunk/py/_test/cmdline.py (props changed) pypy/trunk/py/_test/collect.py (props changed) pypy/trunk/py/_test/config.py (props changed) pypy/trunk/py/_test/conftesthandle.py (props changed) pypy/trunk/py/_test/funcargs.py (props changed) pypy/trunk/py/_test/parseopt.py (props changed) pypy/trunk/py/_test/pluginmanager.py (props changed) pypy/trunk/py/_test/pycollect.py (props changed) pypy/trunk/py/_test/session.py (props changed) pypy/trunk/py/_xmlgen.py (props changed) pypy/trunk/py/apipkg.py (props changed) Log: fixeol From afa at codespeak.net Wed Jun 9 12:09:01 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 12:09:01 +0200 (CEST) Subject: [pypy-svn] r75233 - pypy/branch/cpyext-init-cleanup/pypy/module/cpyext Message-ID: <20100609100901.C1F9E282BFA@codespeak.net> Author: afa Date: Wed Jun 9 12:09:00 2010 New Revision: 75233 Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Log: Remove unused parameter Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 12:09:00 2010 @@ -752,7 +752,7 @@ struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) - functions = generate_decls_and_callbacks(db, export_symbols) + functions = generate_decls_and_callbacks(db) global_objects = [] for obj in GLOBALS.values(): @@ -830,7 +830,7 @@ pypy_macros_h = udir.join('pypy_macros.h') pypy_macros_h.write('\n'.join(pypy_macros)) -def generate_decls_and_callbacks(db, export_symbols, api_struct=True): +def generate_decls_and_callbacks(db, api_struct=True): "NOT_RPYTHON" # implement function callbacks and generate function decls functions = [] @@ -924,7 +924,7 @@ generate_macros(export_symbols, rename=False) - functions = generate_decls_and_callbacks(db, [], api_struct=False) + functions = generate_decls_and_callbacks(db, api_struct=False) code = "#include \n" + "\n".join(functions) eci = build_eci(False, export_symbols, code) From arigo at codespeak.net Wed Jun 9 12:16:03 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 12:16:03 +0200 (CEST) Subject: [pypy-svn] r75234 - pypy/trunk/lib-python/modified-2.5.2/distutils/tests Message-ID: <20100609101603.821E8282BFA@codespeak.net> Author: arigo Date: Wed Jun 9 12:16:02 2010 New Revision: 75234 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py Log: Attempt to skip this file on non-Windows platforms. Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py Wed Jun 9 12:16:02 2010 @@ -1,8 +1,8 @@ -import unittest -from distutils.msvccompiler import get_manifests +import unittest, sys class MsvcCompilerTestCase(unittest.TestCase): def test_get_manifests(self): + from distutils.msvccompiler import get_manifests manifests = get_manifests() self.assert_(manifests) for manifest in manifests: @@ -12,7 +12,10 @@ self.fail("could not find a suitable manifest") def test_suite(): - return unittest.makeSuite(MsvcCompilerTestCase) + if sys.platform == 'win32': + return unittest.makeSuite(MsvcCompilerTestCase) + else: + return unittest.TestSuite([]) if __name__ == "__main__": unittest.main(defaultTest="test_suite") From arigo at codespeak.net Wed Jun 9 12:22:16 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 12:22:16 +0200 (CEST) Subject: [pypy-svn] r75235 - pypy/trunk/pypy/module/sys Message-ID: <20100609102216.C2DA2282BFA@codespeak.net> Author: arigo Date: Wed Jun 9 12:22:15 2010 New Revision: 75235 Modified: pypy/trunk/pypy/module/sys/interp_encoding.py Log: Revert r75039. It makes pypy-c -A tests fail on tannit, and it is entirely undocumented apart from the commit message "Obscure specialcase". Reverting it seems to not make any test in the sys module fail either. Modified: pypy/trunk/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/trunk/pypy/module/sys/interp_encoding.py (original) +++ pypy/trunk/pypy/module/sys/interp_encoding.py Wed Jun 9 12:22:15 2010 @@ -43,8 +43,6 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: - if loc_codeset == 'ANSI_X3.4-1968': - loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), From arigo at codespeak.net Wed Jun 9 14:54:33 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 14:54:33 +0200 (CEST) Subject: [pypy-svn] r75236 - in pypy/trunk/pypy: annotation annotation/test objspace/std rlib rpython rpython/lltypesystem rpython/test Message-ID: <20100609125433.53D6E282BDA@codespeak.net> Author: arigo Date: Wed Jun 9 14:54:29 2010 New Revision: 75236 Modified: pypy/trunk/pypy/annotation/builtin.py pypy/trunk/pypy/annotation/classdef.py pypy/trunk/pypy/annotation/test/test_annrpython.py pypy/trunk/pypy/objspace/std/unicodetype.py pypy/trunk/pypy/rlib/runicode.py pypy/trunk/pypy/rpython/lltypesystem/rstr.py pypy/trunk/pypy/rpython/rbuiltin.py pypy/trunk/pypy/rpython/test/test_rbuiltin.py Log: Revert half of r75146, which was half-done (see e.g. test_runicode failures). I tried to finish it but it gives a growing mess. Instead, I reverted to Unicode{De,En}codeError being RPython exceptions with no attributes, and just pass an error handler when calling rlib/runicode from objspace/std/unicodeobject.py. The error handler knows about the space and raises directly the app-level exception. Modified: pypy/trunk/pypy/annotation/builtin.py ============================================================================== --- pypy/trunk/pypy/annotation/builtin.py (original) +++ pypy/trunk/pypy/annotation/builtin.py Wed Jun 9 14:54:29 2010 @@ -272,12 +272,6 @@ def OSError_init(s_self, *args): pass -def UnicodeDecodeError_init(s_self, *args): - pass - -def UnicodeEncodeError_init(s_self, *args): - pass - def WindowsError_init(s_self, *args): pass @@ -396,8 +390,6 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) -BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init -BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError Modified: pypy/trunk/pypy/annotation/classdef.py ============================================================================== --- pypy/trunk/pypy/annotation/classdef.py (original) +++ pypy/trunk/pypy/annotation/classdef.py Wed Jun 9 14:54:29 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString, SomeUnicodeString + SomeString from pypy.annotation import description @@ -439,16 +439,6 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, - UnicodeDecodeError: {'end': SomeInteger(), - 'start': SomeInteger(), - 'object': SomeString(), - 'encoding': SomeString(), - 'reason': SomeString()}, - UnicodeEncodeError: {'end': SomeInteger(), - 'start': SomeInteger(), - 'object': SomeUnicodeString(), - 'encoding': SomeString(), - 'reason': SomeString()} } try: Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Wed Jun 9 14:54:29 2010 @@ -3332,16 +3332,6 @@ a = self.RPythonAnnotator() py.test.raises(AssertionError, a.build_types, f, []) - def test_unicode_decode_error(self): - def f(): - try: - raise UnicodeDecodeError("x", "x", 0, 1, "reason") - except UnicodeDecodeError, ude: - return ude.end - - a = self.RPythonAnnotator() - s = a.build_types(f, []) - assert isinstance(s, annmodel.SomeInteger) def g(n): return [0,1,2,n] Modified: pypy/trunk/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/trunk/pypy/objspace/std/unicodetype.py (original) +++ pypy/trunk/pypy/objspace/std/unicodetype.py Wed Jun 9 14:54:29 2010 @@ -170,6 +170,32 @@ # ____________________________________________________________ +def decode_error_handler(space): + def raise_unicode_exception_decode(errors, encoding, msg, s, + startingpos, endingpos): + raise OperationError(space.w_UnicodeDecodeError, + space.newtuple([space.wrap(encoding), + space.wrap(s), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_decode +decode_error_handler._annspecialcase_ = 'specialize:memo' + +def encode_error_handler(space): + def raise_unicode_exception_encode(errors, encoding, msg, u, + startingpos, endingpos): + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([space.wrap(encoding), + space.wrap(u), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_encode +encode_error_handler._annspecialcase_ = 'specialize:memo' + +# ____________________________________________________________ + def getdefaultencoding(space): return space.sys.defaultencoding @@ -191,21 +217,16 @@ w_encoder = space.sys.get_w_default_encoder() else: if errors is None or errors == 'strict': - try: - if encoding == 'ascii': - u = space.unicode_w(w_object) - return space.wrap(unicode_encode_ascii(u, len(u), None)) - if encoding == 'utf-8': - u = space.unicode_w(w_object) - return space.wrap(unicode_encode_utf_8(u, len(u), None)) - except UnicodeEncodeError, uee: - raise OperationError(space.w_UnicodeEncodeError, - space.newtuple([ - space.wrap(uee.encoding), - space.wrap(uee.object), - space.wrap(uee.start), - space.wrap(uee.end), - space.wrap(uee.reason)])) + if encoding == 'ascii': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_ascii(u, len(u), None, + errorhandler=eh)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_utf_8(u, len(u), None, + errorhandler=eh)) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -224,19 +245,17 @@ if encoding is None: encoding = getdefaultencoding(space) if errors is None or errors == 'strict': - try: - if encoding == 'ascii': - # XXX error handling - s = space.bufferstr_w(w_obj) - return space.wrap(str_decode_ascii(s, len(s), None)[0]) - if encoding == 'utf-8': - s = space.bufferstr_w(w_obj) - return space.wrap(str_decode_utf_8(s, len(s), None)[0]) - except UnicodeDecodeError, ude: - raise OperationError(space.w_UnicodeDecodeError, space.newtuple( - [space.wrap(ude.encoding), space.wrap(ude.object), - space.wrap(ude.start), space.wrap(ude.end), - space.wrap(ude.reason)])) + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_ascii(s, len(s), None, + errorhandler=eh)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_utf_8(s, len(s), None, + errorhandler=eh)[0]) w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Wed Jun 9 14:54:29 2010 @@ -48,14 +48,12 @@ def raise_unicode_exception_decode(errors, encoding, msg, s, startingpos, endingpos): assert isinstance(s, str) - raise UnicodeDecodeError( - encoding, s[startingpos], startingpos, endingpos, msg) + raise UnicodeDecodeError(encoding, s, startingpos, endingpos, msg) def raise_unicode_exception_encode(errors, encoding, msg, u, startingpos, endingpos): assert isinstance(u, unicode) - raise UnicodeEncodeError( - encoding, u[startingpos], startingpos, endingpos, msg) + raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg) # ____________________________________________________________ # unicode decoding Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rstr.py Wed Jun 9 14:54:29 2010 @@ -18,7 +18,6 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name -from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -297,7 +296,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) + raise UnicodeDecodeError s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' Modified: pypy/trunk/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/rbuiltin.py Wed Jun 9 14:54:29 2010 @@ -270,37 +270,6 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) -def rtype_UnicodeDecodeError_init(hop): - if hop.nb_args != 6: - raise TypeError("UnicodeDecodeError() should be called with 5 " - "arguments") - r_self = hop.args_r[0] - r_str = hop.rtyper.type_system.rstr.string_repr - TPS = [hop.args_r[0], r_str, r_str, lltype.Signed, lltype.Signed, - r_str] - v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) - r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) - r_self.setfield(v_self, 'object', v_obj, hop.llops) - r_self.setfield(v_self, 'start', v_start, hop.llops) - r_self.setfield(v_self, 'end', v_end, hop.llops) - r_self.setfield(v_self, 'reason', v_msg, hop.llops) - -def rtype_UnicodeEncodeError_init(hop): - if hop.nb_args != 6: - raise TypeError("UnicodeEncodeError() should be called with 5 " - "arguments") - r_self = hop.args_r[0] - r_str = hop.rtyper.type_system.rstr.string_repr - r_unicode = hop.rtyper.type_system.rstr.unicode_repr - TPS = [hop.args_r[0], r_str, r_unicode, lltype.Signed, lltype.Signed, - r_str] - v_self, v_encoding, v_obj, v_start, v_end, v_msg = hop.inputargs(*TPS) - r_self.setfield(v_self, 'encoding', v_encoding, hop.llops) - r_self.setfield(v_self, 'object', v_obj, hop.llops) - r_self.setfield(v_self, 'start', v_start, hop.llops) - r_self.setfield(v_self, 'end', v_end, hop.llops) - r_self.setfield(v_self, 'reason', v_msg, hop.llops) - def rtype_WindowsError__init__(hop): if hop.nb_args == 2: raise TyperError("WindowsError() should not be called with " @@ -360,8 +329,6 @@ BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( rtype_OSError__init__) -BUILTIN_TYPER[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = rtype_UnicodeDecodeError_init -BUILTIN_TYPER[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = rtype_UnicodeEncodeError_init try: WindowsError Modified: pypy/trunk/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/test/test_rbuiltin.py Wed Jun 9 14:54:29 2010 @@ -496,35 +496,6 @@ res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy()) assert res == 123 - def test_unicode_errors(self): - def f(): - try: - raise UnicodeDecodeError("xx", "x", 0, 1, "reason") - except UnicodeDecodeError, ude: - assert ude.start == 0 - assert ude.encoding == "xx" - assert ude.object == "x" - assert ude.start == 0 - assert ude.reason == "reason" - return ude.end - - res = self.interpret(f, []) - assert res == f() - - def f(): - try: - raise UnicodeEncodeError("xx", u"x", 0, 1, "reason") - except UnicodeEncodeError, ude: - assert ude.start == 0 - assert ude.encoding == "xx" - assert ude.object == u"x" - assert ude.start == 0 - assert ude.reason == "reason" - return ude.end - - res = self.interpret(f, []) - assert res == f() - class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): From afa at codespeak.net Wed Jun 9 17:56:52 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 9 Jun 2010 17:56:52 +0200 (CEST) Subject: [pypy-svn] r75237 - in pypy/branch/cpyext-init-cleanup/pypy/module/cpyext: . test Message-ID: <20100609155652.475ED282BD6@codespeak.net> Author: afa Date: Wed Jun 9 17:56:49 2010 New Revision: 75237 Added: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/gateway.py Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/boolobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/classobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/complexobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/dictobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/eval.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/floatobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/funcobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/import_.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/intobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/iterator.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/longobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/mapping.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/methodobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/modsupport.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/number.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/object.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyerrors.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pystate.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pythonrun.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/structmember.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubsactive.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sysmodule.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_api.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_borrow.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_cpyext.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/thread.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/tupleobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/weakrefobject.py Log: Split the large api.py, and move cross-language functions calls into gateway.py Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/api.py Wed Jun 9 17:56:49 2010 @@ -13,10 +13,10 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.gensupp import NameManager from pypy.tool.udir import udir +from pypy.tool.sourcetools import func_with_new_name from pypy.translator import platform -from pypy.module.cpyext.state import State -from pypy.interpreter.error import OperationError, operationerrfmt -from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.interpreter.error import operationerrfmt +from pypy.interpreter.baseobjspace import ObjSpace from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.nestedscope import Cell from pypy.interpreter.module import Module @@ -32,8 +32,6 @@ from pypy.module.exceptions import interp_exceptions # CPython 2.4 compatibility from py.builtin import BaseException -from pypy.tool.sourcetools import func_with_new_name -from pypy.rpython.lltypesystem.lloperation import llop DEBUG_WRAPPER = True @@ -112,43 +110,15 @@ def get_interpret(self, space): raise NotImplementedError -def copy_header_files(): - for name in ("pypy_decl.h", "pypy_macros.h"): - udir.join(name).copy(interfaces_dir / name) - -_NOT_SPECIFIED = object() -CANNOT_FAIL = object() - -# The same function can be called in three different contexts: -# (1) from C code -# (2) in the test suite, though the "api" object -# (3) from RPython code, for example in the implementation of another function. -# -# In contexts (2) and (3), a function declaring a PyObject argument type will -# receive a wrapped pypy object if the parameter name starts with 'w_', a -# reference (= rffi pointer) otherwise; conversion is automatic. Context (2) -# only allows calls with a wrapped object. -# -# Functions with a PyObject return type should return a wrapped object. -# -# Functions may raise exceptions. In context (3), the exception flows normally -# through the calling function. In context (1) and (2), the exception is -# caught; if it is an OperationError, it is stored in the thread state; other -# exceptions generate a OperationError(w_SystemError); and the funtion returns -# the error value specifed in the API. -# - cpyext_namespace = NameManager('cpyext_') class ApiFunction(BaseApiObject): - def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, - c_name=None): + def __init__(self, argtypes, restype, callable, error, c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable - if error is not _NOT_SPECIFIED: - self.error_value = error + self.error_value = error self.c_name = c_name # extract the signature from user code object @@ -165,7 +135,7 @@ def get_llpointer(self, space): "Returns a C function pointer" - assert not we_are_translated() + assert not we_are_translated() # NOT_RPYTHON?? llh = getattr(self, '_llhelper', None) if llh is None: llh = llhelper(self.functype, self._get_wrapper(space)) @@ -181,6 +151,7 @@ def _get_wrapper(self, space): wrapper = getattr(self, '_wrapper', None) if wrapper is None: + from pypy.module.cpyext.gateway import make_wrapper wrapper = make_wrapper(space, self.callable) self._wrapper = wrapper wrapper.relax_sig_check = True @@ -188,114 +159,16 @@ wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper -def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): - """ - Declares a function to be exported. - - `argtypes`, `restype` are lltypes and describe the function signature. - - `error` is the value returned when an applevel exception is raised. The - special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual - exception into a wrapped SystemError. Unwrapped exceptions also cause a - SytemError. - - set `external` to False to get a C function pointer, but not exported by - the API headers. - """ - if error is _NOT_SPECIFIED: - if restype is PyObject: - error = lltype.nullptr(restype.TO) - elif restype is lltype.Void: - error = CANNOT_FAIL - if type(error) is int: - error = rffi.cast(restype, error) - - def decorate(func): - func_name = func.func_name - if external: - c_name = None - else: - c_name = func_name - api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) - func.api_func = api_function - - if external: - assert func_name not in FUNCTIONS, ( - "%s already registered" % func_name) - - if error is _NOT_SPECIFIED: - raise ValueError("function %s has no return value for exceptions" - % func) - def make_unwrapper(catch_exception): - names = api_function.argnames - types_names_enum_ui = unrolling_iterable(enumerate( - zip(api_function.argtypes, - [tp_name.startswith("w_") for tp_name in names]))) - - @specialize.ll() - def unwrapper(space, *args): - from pypy.module.cpyext.pyobject import Py_DecRef - from pypy.module.cpyext.pyobject import make_ref, from_ref - from pypy.module.cpyext.pyobject import BorrowPair - newargs = () - to_decref = [] - assert len(args) == len(api_function.argtypes) - for i, (ARG, is_wrapped) in types_names_enum_ui: - input_arg = args[i] - if is_PyObject(ARG) and not is_wrapped: - # build a reference - if input_arg is None: - arg = lltype.nullptr(PyObject.TO) - elif isinstance(input_arg, W_Root): - ref = make_ref(space, input_arg) - to_decref.append(ref) - arg = rffi.cast(ARG, ref) - else: - arg = input_arg - elif is_PyObject(ARG) and is_wrapped: - # convert to a wrapped object - if input_arg is None: - arg = input_arg - elif isinstance(input_arg, W_Root): - arg = input_arg - else: - arg = from_ref(space, - rffi.cast(PyObject, input_arg)) - else: - arg = input_arg - newargs += (arg, ) - try: - try: - res = func(space, *newargs) - except OperationError, e: - if not catch_exception: - raise - if not hasattr(api_function, "error_value"): - raise - state = space.fromcache(State) - state.set_exception(e) - if is_PyObject(restype): - return None - else: - return api_function.error_value - if res is None: - return None - elif isinstance(res, BorrowPair): - return res.w_borrowed - else: - return res - finally: - for arg in to_decref: - Py_DecRef(space, arg) - unwrapper.func = func - unwrapper.api_func = api_function - unwrapper._always_inline_ = True - return unwrapper - - unwrapper_catch = make_unwrapper(True) - unwrapper_raise = make_unwrapper(False) - if external: - FUNCTIONS[func_name] = api_function - INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests - return unwrapper_raise # used in 'normal' RPython code. - return decorate +def FUNCTION_declare(name, api_func): + assert name not in FUNCTIONS, "%s already registered" % (name,) + FUNCTIONS[name] = api_func + +def INTERPLEVEL_declare(name, obj): + INTERPLEVEL_API[name] = obj + +def copy_header_files(): + for name in ("pypy_decl.h", "pypy_macros.h"): + udir.join(name).copy(interfaces_dir / name) def cpython_struct(name, fields, forward=None): configname = name.replace(' ', '__') @@ -549,17 +422,12 @@ PyVarObject = lltype.Ptr(PyVarObjectStruct) PyObjectP = rffi.CArrayPtr(PyObject) - at specialize.memo() -def is_PyObject(TYPE): - if not isinstance(TYPE, lltype.Ptr): - return False - return hasattr(TYPE.TO, 'c_ob_refcnt') and hasattr(TYPE.TO, 'c_ob_type') - def configure_types(): for name, TYPE in rffi_platform.configure(CConfig).iteritems(): if name in TYPES: TYPES[name].become(TYPE) + def build_type_checkers(type_name, cls=None): """ Builds two api functions: Py_XxxCheck() and Py_XxxCheckExact(). @@ -591,101 +459,13 @@ w_type = get_w_type(space) return space.is_w(w_obj_type, w_type) + from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL check = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)( func_with_new_name(check, check_name)) check_exact = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)( func_with_new_name(check_exact, check_name + "Exact")) return check, check_exact -pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void) - -# Make the wrapper for the cases (1) and (2) -def make_wrapper(space, callable): - "NOT_RPYTHON" - names = callable.api_func.argnames - argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, - [name.startswith("w_") for name in names]))) - fatal_value = callable.api_func.restype._defl() - - @specialize.ll() - def wrapper(*args): - from pypy.module.cpyext.pyobject import make_ref, from_ref - from pypy.module.cpyext.pyobject import BorrowPair - # we hope that malloc removal removes the newtuple() that is - # inserted exactly here by the varargs specializer - llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py - rffi.stackcounter.stacks_counter += 1 - retval = fatal_value - boxed_args = () - try: - if not we_are_translated() and DEBUG_WRAPPER: - print >>sys.stderr, callable, - assert len(args) == len(callable.api_func.argtypes) - for i, (typ, is_wrapped) in argtypes_enum_ui: - arg = args[i] - if is_PyObject(typ) and is_wrapped: - if arg: - arg_conv = from_ref(space, rffi.cast(PyObject, arg)) - else: - arg_conv = None - else: - arg_conv = arg - boxed_args += (arg_conv, ) - state = space.fromcache(State) - try: - result = callable(space, *boxed_args) - if not we_are_translated() and DEBUG_WRAPPER: - print >>sys.stderr, " DONE" - except OperationError, e: - failed = True - state.set_exception(e) - except BaseException, e: - failed = True - if not we_are_translated(): - message = repr(e) - import traceback - traceback.print_exc() - else: - message = str(e) - state.set_exception(OperationError(space.w_SystemError, - space.wrap(message))) - else: - failed = False - - if failed: - error_value = callable.api_func.error_value - if error_value is CANNOT_FAIL: - raise SystemError("The function '%s' was not supposed to fail" - % (callable.__name__,)) - retval = error_value - - elif is_PyObject(callable.api_func.restype): - if result is None: - retval = make_ref(space, None) - elif isinstance(result, BorrowPair): - retval = result.get_ref(space) - elif not rffi._isllptr(result): - retval = rffi.cast(callable.api_func.restype, - make_ref(space, result)) - else: - retval = result - elif callable.api_func.restype is not lltype.Void: - retval = rffi.cast(callable.api_func.restype, result) - except Exception, e: - if not we_are_translated(): - import traceback - traceback.print_exc() - print str(e) - # we can't do much here, since we're in ctypes, swallow - else: - print str(e) - pypy_debug_catch_fatal_exception() - rffi.stackcounter.stacks_counter -= 1 - return retval - callable._always_inline_ = True - wrapper.__name__ = "wrapper for %r" % (callable, ) - return wrapper - def setup_init_functions(eci): init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void, compilation_info=eci) init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void, compilation_info=eci) @@ -948,6 +728,8 @@ initfunctype = lltype.Ptr(lltype.FuncType([], lltype.Void)) @unwrap_spec(ObjSpace, str, str) def load_extension_module(space, path, name): + from pypy.module.cpyext.state import State + from pypy.module.cpyext.gateway import generic_cpy_call state = space.fromcache(State) state.package_context = name try: @@ -974,113 +756,3 @@ finally: state.package_context = None - at specialize.ll() -def generic_cpy_call(space, func, *args): - FT = lltype.typeOf(func).TO - return make_generic_cpy_call(FT, True, False)(space, func, *args) - - at specialize.ll() -def generic_cpy_call_dont_decref(space, func, *args): - FT = lltype.typeOf(func).TO - return make_generic_cpy_call(FT, False, False)(space, func, *args) - - at specialize.ll() -def generic_cpy_call_expect_null(space, func, *args): - FT = lltype.typeOf(func).TO - return make_generic_cpy_call(FT, True, True)(space, func, *args) - - at specialize.memo() -def make_generic_cpy_call(FT, decref_args, expect_null): - from pypy.module.cpyext.pyobject import make_ref, from_ref, Py_DecRef - from pypy.module.cpyext.pyobject import RefcountState - from pypy.module.cpyext.pyerrors import PyErr_Occurred - unrolling_arg_types = unrolling_iterable(enumerate(FT.ARGS)) - RESULT_TYPE = FT.RESULT - - # copied and modified from rffi.py - # We need tons of care to ensure that no GC operation and no - # exception checking occurs in call_external_function. - argnames = ', '.join(['a%d' % i for i in range(len(FT.ARGS))]) - source = py.code.Source(""" - def call_external_function(funcptr, %(argnames)s): - # NB. it is essential that no exception checking occurs here! - res = funcptr(%(argnames)s) - return res - """ % locals()) - miniglobals = {'__name__': __name__, # for module name propagation - } - exec source.compile() in miniglobals - call_external_function = miniglobals['call_external_function'] - call_external_function._dont_inline_ = True - call_external_function._annspecialcase_ = 'specialize:ll' - call_external_function._gctransformer_hint_close_stack_ = True - call_external_function = func_with_new_name(call_external_function, - 'ccall_' + name) - # don't inline, as a hack to guarantee that no GC pointer is alive - # anywhere in call_external_function - - @specialize.ll() - def generic_cpy_call(space, func, *args): - boxed_args = () - to_decref = [] - assert len(args) == len(FT.ARGS) - for i, ARG in unrolling_arg_types: - arg = args[i] - if is_PyObject(ARG): - if arg is None: - boxed_args += (lltype.nullptr(PyObject.TO),) - elif isinstance(arg, W_Root): - ref = make_ref(space, arg) - boxed_args += (ref,) - if decref_args: - to_decref.append(ref) - else: - boxed_args += (arg,) - else: - boxed_args += (arg,) - - try: - # create a new container for borrowed references - state = space.fromcache(RefcountState) - old_container = state.swap_borrow_container(None) - try: - # Call the function - result = call_external_function(func, *boxed_args) - finally: - state.swap_borrow_container(old_container) - - if is_PyObject(RESULT_TYPE): - if result is None: - ret = result - elif isinstance(result, W_Root): - ret = result - else: - ret = from_ref(space, result) - # The object reference returned from a C function - # that is called from Python must be an owned reference - # - ownership is transferred from the function to its caller. - if result: - Py_DecRef(space, result) - - # Check for exception consistency - has_error = PyErr_Occurred(space) is not None - has_result = ret is not None - if has_error and has_result: - raise OperationError(space.w_SystemError, space.wrap( - "An exception was set, but function returned a value")) - elif not expect_null and not has_error and not has_result: - raise OperationError(space.w_SystemError, space.wrap( - "Function returned a NULL result without setting an exception")) - - if has_error: - state = space.fromcache(State) - state.check_and_raise_exception() - - return ret - return result - finally: - if decref_args: - for ref in to_decref: - Py_DecRef(space, ref) - return generic_cpy_call - Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/boolobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/boolobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/boolobject.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import (cpython_api, PyObject, CANNOT_FAIL, - build_type_checkers) +from pypy.module.cpyext.gateway import ( + cpython_api, CANNOT_FAIL) +from pypy.module.cpyext.api import PyObject, build_type_checkers # Inheriting from bool isn't actually possible. PyBool_Check = build_type_checkers("Bool")[1] Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/classobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/classobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/classobject.py Wed Jun 9 17:56:49 2010 @@ -1,10 +1,12 @@ from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL from pypy.module.cpyext.api import ( - PyObjectFields, CANNOT_FAIL, - cpython_api, bootstrap_function, cpython_struct, build_type_checkers) -from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref, Py_DecRef, make_typedescr + PyObjectFields, bootstrap_function, cpython_struct, build_type_checkers) +from pypy.module.cpyext.pyobject import ( + PyObject, make_ref, from_ref, Py_DecRef, make_typedescr) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall -from pypy.module.__builtin__.interp_classobj import W_ClassObject, W_InstanceObject +from pypy.module.__builtin__.interp_classobj import ( + W_ClassObject, W_InstanceObject) PyClass_Check, PyClass_CheckExact = build_type_checkers("Class", W_ClassObject) PyInstance_Check, PyInstance_CheckExact = build_type_checkers("Instance", W_InstanceObject) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/complexobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/complexobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/complexobject.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import lltype, rffi -from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, PyObject, build_type_checkers) +from pypy.module.cpyext.gateway import cpython_api +from pypy.module.cpyext.api import cpython_struct, build_type_checkers +from pypy.module.cpyext.pyobject import PyObject from pypy.module.cpyext.pyerrors import PyErr_BadArgument from pypy.module.cpyext.floatobject import PyFloat_AsDouble from pypy.objspace.std.complexobject import W_ComplexObject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/datetime.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pyobject import PyObject, make_ref -from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import cpython_struct, PyObjectFields from pypy.module.cpyext.import_ import PyImport_Import from pypy.module.cpyext.typeobject import PyTypeObjectPtr from pypy.interpreter.error import OperationError Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/dictobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/dictobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/dictobject.py Wed Jun 9 17:56:49 2010 @@ -1,9 +1,9 @@ from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, build_type_checkers, Py_ssize_t, - Py_ssize_tP, CONST_STRING) -from pypy.module.cpyext.pyobject import PyObject, PyObjectP, borrow_from -from pypy.module.cpyext.pyobject import RefcountState + build_type_checkers, Py_ssize_t, Py_ssize_tP, CONST_STRING) +from pypy.module.cpyext.pyobject import ( + PyObject, PyObjectP, borrow_from, RefcountState) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall from pypy.interpreter.error import OperationError Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/eval.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/eval.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/eval.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,8 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP) + CONST_STRING, FILEP, fread, feof, Py_ssize_tP) from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno from pypy.module.__builtin__ import compiling Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/floatobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/floatobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/floatobject.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import (CANNOT_FAIL, cpython_api, PyObject, - build_type_checkers) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import PyObject, build_type_checkers from pypy.interpreter.error import OperationError PyFloat_Check, PyFloat_CheckExact = build_type_checkers("Float") Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/funcobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/funcobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/funcobject.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api, generic_cpy_call from pypy.module.cpyext.api import ( - PyObjectFields, generic_cpy_call, - cpython_api, bootstrap_function, cpython_struct, build_type_checkers) + cpython_struct, build_type_checkers, PyObjectFields, bootstrap_function) from pypy.module.cpyext.pyobject import ( PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from) from pypy.interpreter.function import Function, Method Added: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/gateway.py ============================================================================== --- (empty file) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/gateway.py Wed Jun 9 17:56:49 2010 @@ -0,0 +1,343 @@ +from pypy.interpreter.baseobjspace import W_Root +from pypy.interpreter.error import OperationError +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.objectmodel import specialize, we_are_translated +from pypy.module.cpyext.api import ( + ApiFunction, FUNCTION_declare, INTERPLEVEL_declare, PyObject) +from pypy.module.cpyext.state import State +from pypy.rlib.unroll import unrolling_iterable +import sys +import py + +# The same function can be called in three different contexts: +# (1) from C code +# (2) in the test suite, though the "api" object +# (3) from RPython code, for example in the implementation of another function. +# +# In contexts (2) and (3), a function declaring a PyObject argument type will +# receive a wrapped pypy object if the parameter name starts with 'w_', a +# reference (= rffi pointer) otherwise; conversion is automatic. Context (2) +# only allows calls with a wrapped object. +# +# Functions with a PyObject return type should return a wrapped object. +# +# Functions may raise exceptions. In context (3), the exception flows normally +# through the calling function. In context (1) and (2), the exception is +# caught; if it is an OperationError, it is stored in the thread state; other +# exceptions generate a OperationError(w_SystemError); and the funtion returns +# the error value specifed in the API. +# + +DEBUG_WRAPPER = True + +_NOT_SPECIFIED = object() +CANNOT_FAIL = object() + +pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void) + + at specialize.memo() +def is_PyObject(TYPE): + if not isinstance(TYPE, lltype.Ptr): + return False + return hasattr(TYPE.TO, 'c_ob_refcnt') and hasattr(TYPE.TO, 'c_ob_type') + +def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): + """ + Declares a function to be exported. + - `argtypes`, `restype` are lltypes and describe the function signature. + - `error` is the value returned when an applevel exception is raised. The + special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual + exception into a wrapped SystemError. Unwrapped exceptions also cause a + SytemError. + - set `external` to False to get a C function pointer, but not exported by + the API headers. + """ + if error is _NOT_SPECIFIED: + if restype is PyObject: + error = lltype.nullptr(restype.TO) + elif restype is lltype.Void: + error = CANNOT_FAIL + if type(error) is int: + error = rffi.cast(restype, error) + + def decorate(func): + func_name = func.func_name + if external: + c_name = None + else: + c_name = func_name + api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) + func.api_func = api_function + + if error is _NOT_SPECIFIED: + raise ValueError("function %s has no return value for exceptions" + % func) + def make_unwrapper(catch_exception): + names = api_function.argnames + types_names_enum_ui = unrolling_iterable(enumerate( + zip(api_function.argtypes, + [tp_name.startswith("w_") for tp_name in names]))) + + @specialize.ll() + def unwrapper(space, *args): + from pypy.module.cpyext.pyobject import Py_DecRef + from pypy.module.cpyext.pyobject import make_ref, from_ref + from pypy.module.cpyext.pyobject import BorrowPair + newargs = () + to_decref = [] + assert len(args) == len(api_function.argtypes) + for i, (ARG, is_wrapped) in types_names_enum_ui: + input_arg = args[i] + if is_PyObject(ARG) and not is_wrapped: + # build a reference + if input_arg is None: + arg = lltype.nullptr(PyObject.TO) + elif isinstance(input_arg, W_Root): + ref = make_ref(space, input_arg) + to_decref.append(ref) + arg = rffi.cast(ARG, ref) + else: + arg = input_arg + elif is_PyObject(ARG) and is_wrapped: + # convert to a wrapped object + if input_arg is None: + arg = input_arg + elif isinstance(input_arg, W_Root): + arg = input_arg + else: + arg = from_ref(space, + rffi.cast(PyObject, input_arg)) + else: + arg = input_arg + newargs += (arg, ) + try: + try: + res = func(space, *newargs) + except OperationError, e: + if not catch_exception: + raise + state = space.fromcache(State) + state.set_exception(e) + if is_PyObject(restype): + return None + else: + if api_function.error_value is _NOT_SPECIFIED: + raise + return api_function.error_value + if res is None: + return None + elif isinstance(res, BorrowPair): + return res.w_borrowed + else: + return res + finally: + for arg in to_decref: + Py_DecRef(space, arg) + unwrapper.func = func + unwrapper.api_func = api_function + unwrapper._always_inline_ = True + return unwrapper + + unwrapper_catch = make_unwrapper(True) + unwrapper_raise = make_unwrapper(False) + if external: + FUNCTION_declare(func_name, api_function) + INTERPLEVEL_declare(func_name, unwrapper_catch) # used in tests + return unwrapper_raise # used in 'normal' RPython code. + return decorate + +# Make the wrapper for the cases (1) and (2) +def make_wrapper(space, callable): + "NOT_RPYTHON" + names = callable.api_func.argnames + argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, + [name.startswith("w_") for name in names]))) + fatal_value = callable.api_func.restype._defl() + + @specialize.ll() + def wrapper(*args): + from pypy.module.cpyext.pyobject import make_ref, from_ref + from pypy.module.cpyext.pyobject import BorrowPair + # we hope that malloc removal removes the newtuple() that is + # inserted exactly here by the varargs specializer + llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py + rffi.stackcounter.stacks_counter += 1 + retval = fatal_value + boxed_args = () + try: + if not we_are_translated() and DEBUG_WRAPPER: + print >>sys.stderr, callable, + assert len(args) == len(callable.api_func.argtypes) + for i, (typ, is_wrapped) in argtypes_enum_ui: + arg = args[i] + if is_PyObject(typ) and is_wrapped: + if arg: + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) + else: + arg_conv = None + else: + arg_conv = arg + boxed_args += (arg_conv, ) + state = space.fromcache(State) + try: + result = callable(space, *boxed_args) + if not we_are_translated() and DEBUG_WRAPPER: + print >>sys.stderr, " DONE" + except OperationError, e: + failed = True + state.set_exception(e) + except BaseException, e: + failed = True + if not we_are_translated(): + message = repr(e) + import traceback + traceback.print_exc() + else: + message = str(e) + state.set_exception(OperationError(space.w_SystemError, + space.wrap(message))) + else: + failed = False + + if failed: + error_value = callable.api_func.error_value + if error_value is CANNOT_FAIL: + raise SystemError("The function '%s' was not supposed to fail" + % (callable.__name__,)) + retval = error_value + + elif is_PyObject(callable.api_func.restype): + if result is None: + retval = make_ref(space, None) + elif isinstance(result, BorrowPair): + retval = result.get_ref(space) + elif not rffi._isllptr(result): + retval = rffi.cast(callable.api_func.restype, + make_ref(space, result)) + else: + retval = result + elif callable.api_func.restype is not lltype.Void: + retval = rffi.cast(callable.api_func.restype, result) + except Exception, e: + if not we_are_translated(): + import traceback + traceback.print_exc() + print str(e) + # we can't do much here, since we're in ctypes, swallow + else: + print str(e) + pypy_debug_catch_fatal_exception() + rffi.stackcounter.stacks_counter -= 1 + return retval + callable._always_inline_ = True + wrapper.__name__ = "wrapper for %r" % (callable, ) + return wrapper + + at specialize.ll() +def generic_cpy_call(space, func, *args): + FT = lltype.typeOf(func).TO + return make_generic_cpy_call(FT, True, False)(space, func, *args) + + at specialize.ll() +def generic_cpy_call_dont_decref(space, func, *args): + FT = lltype.typeOf(func).TO + return make_generic_cpy_call(FT, False, False)(space, func, *args) + + at specialize.ll() +def generic_cpy_call_expect_null(space, func, *args): + FT = lltype.typeOf(func).TO + return make_generic_cpy_call(FT, True, True)(space, func, *args) + + at specialize.memo() +def make_generic_cpy_call(FT, decref_args, expect_null): + from pypy.module.cpyext.pyobject import make_ref, from_ref, Py_DecRef + from pypy.module.cpyext.pyobject import RefcountState + from pypy.module.cpyext.pyerrors import PyErr_Occurred + unrolling_arg_types = unrolling_iterable(enumerate(FT.ARGS)) + RESULT_TYPE = FT.RESULT + + # copied and modified from rffi.py + # We need tons of care to ensure that no GC operation and no + # exception checking occurs in call_external_function. + argnames = ', '.join(['a%d' % i for i in range(len(FT.ARGS))]) + source = py.code.Source(""" + def call_cpyext_external_function(funcptr, %(argnames)s): + # NB. it is essential that no exception checking occurs here! + res = funcptr(%(argnames)s) + return res + """ % locals()) + miniglobals = {'__name__': __name__, # for module name propagation + } + exec source.compile() in miniglobals + call_external_function = miniglobals['call_cpyext_external_function'] + call_external_function._dont_inline_ = True + call_external_function._annspecialcase_ = 'specialize:ll' + call_external_function._gctransformer_hint_close_stack_ = True + # don't inline, as a hack to guarantee that no GC pointer is alive + # anywhere in call_external_function + + @specialize.ll() + def generic_cpy_call(space, func, *args): + boxed_args = () + to_decref = [] + assert len(args) == len(FT.ARGS) + for i, ARG in unrolling_arg_types: + arg = args[i] + if is_PyObject(ARG): + if arg is None: + boxed_args += (lltype.nullptr(PyObject.TO),) + elif isinstance(arg, W_Root): + ref = make_ref(space, arg) + boxed_args += (ref,) + if decref_args: + to_decref.append(ref) + else: + boxed_args += (arg,) + else: + boxed_args += (arg,) + + try: + # create a new container for borrowed references + state = space.fromcache(RefcountState) + old_container = state.swap_borrow_container(None) + try: + # Call the function + result = call_external_function(func, *boxed_args) + finally: + state.swap_borrow_container(old_container) + + if is_PyObject(RESULT_TYPE): + if result is None: + ret = result + elif isinstance(result, W_Root): + ret = result + else: + ret = from_ref(space, result) + # The object reference returned from a C function + # that is called from Python must be an owned reference + # - ownership is transferred from the function to its caller. + if result: + Py_DecRef(space, result) + + # Check for exception consistency + has_error = PyErr_Occurred(space) is not None + has_result = ret is not None + if has_error and has_result: + raise OperationError(space.w_SystemError, space.wrap( + "An exception was set, but function returned a value")) + elif not expect_null and not has_error and not has_result: + raise OperationError(space.w_SystemError, space.wrap( + "Function returned a NULL result without setting an exception")) + + if has_error: + state = space.fromcache(State) + state.check_and_raise_exception() + + return ret + return result + finally: + if decref_args: + for ref in to_decref: + Py_DecRef(space, ref) + return generic_cpy_call Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/import_.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/import_.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/import_.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,6 @@ from pypy.interpreter import module -from pypy.module.cpyext.api import ( - generic_cpy_call, cpython_api, PyObject, CONST_STRING) +from pypy.module.cpyext.gateway import cpython_api, generic_cpy_call +from pypy.module.cpyext.api import PyObject, CONST_STRING from pypy.rpython.lltypesystem import rffi from pypy.interpreter.error import OperationError Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/intobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/intobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/intobject.py Wed Jun 9 17:56:49 2010 @@ -1,8 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import (cpython_api, PyObject, CANNOT_FAIL, - build_type_checkers, Py_ssize_t) - +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import PyObject, Py_ssize_t, build_type_checkers PyInt_Check, PyInt_CheckExact = build_type_checkers("Int") Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/iterator.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/iterator.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/iterator.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError -from pypy.module.cpyext.api import (generic_cpy_call, cpython_api, PyObject, - CANNOT_FAIL) +from pypy.module.cpyext.gateway import ( + generic_cpy_call, cpython_api, CANNOT_FAIL) +from pypy.module.cpyext.pyobject import PyObject import pypy.module.__builtin__.operation as operation from pypy.rpython.lltypesystem import rffi Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/listobject.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, Py_ssize_t, - build_type_checkers) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import Py_ssize_t, build_type_checkers from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall from pypy.module.cpyext.pyobject import Py_DecRef, PyObject, borrow_from from pypy.objspace.std.listobject import W_ListObject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/longobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/longobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/longobject.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import lltype, rffi -from pypy.module.cpyext.api import (cpython_api, PyObject, build_type_checkers, - CONST_STRING, ADDR) +from pypy.module.cpyext.gateway import cpython_api +from pypy.module.cpyext.api import ( + PyObject, CONST_STRING, ADDR, build_type_checkers) from pypy.objspace.std.longobject import W_LongObject from pypy.interpreter.error import OperationError Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/mapping.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/mapping.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/mapping.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import lltype, rffi -from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import CONST_STRING, Py_ssize_t from pypy.module.cpyext.pyobject import PyObject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/methodobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/methodobject.py Wed Jun 9 17:56:49 2010 @@ -6,12 +6,14 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.function import BuiltinFunction, Method, StaticMethod from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import (PyObject, from_ref, make_ref, - make_typedescr, Py_DecRef) +from pypy.module.cpyext.pyobject import ( + PyObject, from_ref, make_ref, make_typedescr, Py_DecRef) +from pypy.module.cpyext.gateway import cpython_api, generic_cpy_call from pypy.module.cpyext.api import ( - generic_cpy_call, cpython_api, PyObject, cpython_struct, METH_KEYWORDS, - METH_O, CONST_STRING, METH_CLASS, METH_STATIC, METH_COEXIST, METH_NOARGS, - METH_VARARGS, build_type_checkers, PyObjectFields, bootstrap_function) + PyObject, cpython_struct, PyObjectFields, bootstrap_function, + build_type_checkers, METH_KEYWORDS, METH_O, METH_CLASS, + METH_STATIC, METH_COEXIST, METH_NOARGS, METH_VARARGS, + CONST_STRING) from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.rlib.objectmodel import we_are_translated from pypy.objspace.std.tupleobject import W_TupleObject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/modsupport.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/modsupport.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/modsupport.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, cpython_struct, \ - METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, CONST_STRING +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import ( + cpython_struct, METH_STATIC, METH_CLASS, METH_COEXIST, CONST_STRING) from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.interpreter.module import Module from pypy.module.cpyext.methodobject import ( Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/number.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/number.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/number.py Wed Jun 9 17:56:49 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError -from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, Py_ssize_t +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import Py_ssize_t from pypy.module.cpyext.pyobject import PyObject from pypy.rpython.lltypesystem import rffi, lltype from pypy.tool.sourcetools import func_with_new_name Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/object.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/object.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/object.py Wed Jun 9 17:56:49 2010 @@ -1,8 +1,10 @@ from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import ( + cpython_api, generic_cpy_call, CANNOT_FAIL) from pypy.module.cpyext.api import ( - cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, - PyVarObject, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, - Py_GE, CONST_STRING, FILEP, fwrite) + Py_ssize_t, Py_ssize_tP, PyVarObject, CONST_STRING, + Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE, + FILEP, fwrite) from pypy.module.cpyext.pyobject import ( PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef, track_reference, get_typedescr, RefcountState) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyerrors.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyerrors.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyerrors.py Wed Jun 9 17:56:49 2010 @@ -2,7 +2,8 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.interpreter.error import OperationError -from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import CONST_STRING from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning from pypy.module.cpyext.pyobject import ( PyObject, PyObjectP, make_ref, Py_DecRef, borrow_from) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pyobject.py Wed Jun 9 17:56:49 2010 @@ -2,9 +2,11 @@ from pypy.interpreter.baseobjspace import W_Root, SpaceCache from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import ( + cpython_api, CANNOT_FAIL) from pypy.module.cpyext.api import ( - cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR, - CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) + bootstrap_function, PyObject, PyObjectP, ADDR, + Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) from pypy.module.cpyext.state import State from pypy.objspace.std.typeobject import W_TypeObject from pypy.rlib.objectmodel import specialize, we_are_translated @@ -382,7 +384,7 @@ obj.c_ob_refcnt = 1 def _Py_Dealloc(space, obj): - from pypy.module.cpyext.api import generic_cpy_call_dont_decref + from pypy.module.cpyext.gateway import generic_cpy_call_dont_decref pto = obj.c_ob_type #print >>sys.stderr, "Calling dealloc slot", pto.c_tp_dealloc, "of", obj, \ # "'s type which is", rffi.charp2str(pto.c_tp_name) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pystate.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pystate.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pystate.py Wed Jun 9 17:56:49 2010 @@ -1,5 +1,6 @@ -from pypy.module.cpyext.api import cpython_api, generic_cpy_call, CANNOT_FAIL,\ - cpython_struct +from pypy.module.cpyext.gateway import ( + cpython_api, generic_cpy_call, CANNOT_FAIL) +from pypy.module.cpyext.api import cpython_struct from pypy.rpython.lltypesystem import rffi, lltype Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pythonrun.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pythonrun.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/pythonrun.py Wed Jun 9 17:56:49 2010 @@ -1,5 +1,5 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL @cpython_api([], rffi.INT_real, error=CANNOT_FAIL) def Py_IsInitialized(space): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sequence.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,7 @@ from pypy.interpreter.error import OperationError -from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import CONST_STRING, Py_ssize_t from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.rpython.lltypesystem import rffi, lltype from pypy.objspace.std import listobject, tupleobject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sliceobject.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,8 @@ from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, bootstrap_function, build_type_checkers, - CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, PyObjectFields) + cpython_struct, build_type_checkers, bootstrap_function, + Py_ssize_t, Py_ssize_tP, PyObjectFields) from pypy.module.cpyext.pyobject import ( Py_DecRef, PyObject, make_ref, make_typedescr) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/slotdefs.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,9 @@ import re from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject +from pypy.module.cpyext.gateway import ( + cpython_api, generic_cpy_call, generic_cpy_call_expect_null) +from pypy.module.cpyext.pyobject import PyObject from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc, @@ -165,7 +167,6 @@ return generic_cpy_call(space, func_target, w_self, start, end) def wrap_next(space, w_self, w_args, func): - from pypy.module.cpyext.api import generic_cpy_call_expect_null func_target = rffi.cast(iternextfunc, func) check_num_args(space, w_args, 0) w_res = generic_cpy_call_expect_null(space, func_target, w_self) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stringobject.py Wed Jun 9 17:56:49 2010 @@ -1,7 +1,8 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype +from pypy.module.cpyext.gateway import cpython_api from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, bootstrap_function, build_type_checkers, + cpython_struct, build_type_checkers, bootstrap_function, PyObjectFields, Py_ssize_t, CONST_STRING) from pypy.module.cpyext.pyobject import ( PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference, Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/structmember.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/structmember.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/structmember.py Wed Jun 9 17:56:49 2010 @@ -2,7 +2,8 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext import structmemberdefs -from pypy.module.cpyext.api import ADDR, PyObjectP, cpython_api +from pypy.module.cpyext.api import ADDR, PyObjectP +from pypy.module.cpyext.gateway import cpython_api from pypy.module.cpyext.intobject import PyInt_AsLong, PyInt_AsUnsignedLong from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, from_ref, make_ref Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubsactive.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubsactive.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/stubsactive.py Wed Jun 9 17:56:49 2010 @@ -1,5 +1,6 @@ from pypy.module.cpyext.pyobject import PyObject -from pypy.module.cpyext.api import cpython_api, Py_ssize_t, CANNOT_FAIL, CConfig +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import Py_ssize_t, CConfig from pypy.module.cpyext.object import FILEP from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pystate import PyThreadState, PyInterpreterState Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sysmodule.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sysmodule.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/sysmodule.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import CANNOT_FAIL, cpython_api, CONST_STRING +from pypy.module.cpyext.gateway import CANNOT_FAIL, cpython_api +from pypy.module.cpyext.api import CONST_STRING from pypy.module.cpyext.pyobject import PyObject, borrow_from @cpython_api([CONST_STRING], PyObject, error=CANNOT_FAIL) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_api.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_api.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_api.py Wed Jun 9 17:56:49 2010 @@ -1,18 +1,19 @@ from pypy.conftest import gettestobjspace from pypy.rpython.lltypesystem import rffi, lltype from pypy.interpreter.baseobjspace import W_Root +from pypy.module.cpyext.api import INTERPLEVEL_API from pypy.module.cpyext.state import State -from pypy.module.cpyext import api +from pypy.module.cpyext.gateway import cpython_api +from pypy.module.cpyext.pyobject import PyObject from pypy.module.cpyext.test.test_cpyext import freeze_refcnts, LeakCheckingTest -PyObject = api.PyObject from pypy.interpreter.error import OperationError from pypy.module.cpyext.state import State import os - at api.cpython_api([PyObject], lltype.Void) + at cpython_api([PyObject], lltype.Void) def PyPy_GetWrapped(space, w_arg): assert isinstance(w_arg, W_Root) - at api.cpython_api([PyObject], lltype.Void) + at cpython_api([PyObject], lltype.Void) def PyPy_GetReference(space, arg): assert lltype.typeOf(arg) == PyObject @@ -36,7 +37,7 @@ def __getattr__(self, name): return getattr(cls.space, name) cls.api = CAPI() - CAPI.__dict__.update(api.INTERPLEVEL_API) + CAPI.__dict__.update(INTERPLEVEL_API) def raises(self, space, api, expected_exc, f, *args): if not callable(f): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_borrow.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_borrow.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_borrow.py Wed Jun 9 17:56:49 2010 @@ -31,6 +31,7 @@ g = PyTuple_GetItem(t, 0); // borrows reference again printf("Refcnt4: %i\\n", f->ob_refcnt); printf("COMPARE: %i\\n", f == g); + fflush(stdout); Py_DECREF(t); Py_RETURN_TRUE; """), Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_cpyext.py Wed Jun 9 17:56:49 2010 @@ -11,17 +11,18 @@ from pypy.translator.gensupp import uniquemodulename from pypy.tool.udir import udir from pypy.module.cpyext import api +from pypy.module.cpyext.gateway import cpython_api from pypy.module.cpyext.state import State from pypy.module.cpyext.pyobject import RefcountState from pypy.module.cpyext.pyobject import Py_DecRef, InvalidPointerException from pypy.translator.goal import autopath from pypy.lib.identity_dict import identity_dict - at api.cpython_api([], api.PyObject) + at cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 - at api.cpython_api([], lltype.Signed, error=-1) + at cpython_api([], lltype.Signed, error=-1) def PyPy_Crash2(space): 1/0 @@ -533,6 +534,7 @@ Py_DECREF(true); Py_DECREF(true); fprintf(stderr, "REFCNT %i %i\\n", refcnt, refcnt_after); + fflush(stderr); return PyBool_FromLong(refcnt_after == refcnt+2 && refcnt < 3); } static PyObject* foo_bar(PyObject* self, PyObject *args) @@ -549,6 +551,7 @@ refcnt_after = true->ob_refcnt; Py_DECREF(tup); fprintf(stderr, "REFCNT2 %i %i\\n", refcnt, refcnt_after); + fflush(stderr); return PyBool_FromLong(refcnt_after == refcnt); } Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_methodobject.py Wed Jun 9 17:56:49 2010 @@ -73,7 +73,7 @@ """ def func(space, w_self, w_args): return space.w_None - c_func = ApiFunction([PyObject, PyObject], PyObject, func) + c_func = ApiFunction([PyObject, PyObject], PyObject, func, error=None) func.api_func = c_func ml = lltype.malloc(PyMethodDef, flavor='raw', zero=True) namebuf = rffi.str2charp('func') Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/test/test_translate.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,6 @@ from pypy.translator.c.test.test_genc import compile -import pypy.module.cpyext.api -from pypy.module.cpyext.api import cpython_api +import pypy.module.cpyext.gateway +from pypy.module.cpyext.gateway import cpython_api from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import lltype from pypy.rlib.objectmodel import specialize @@ -15,7 +15,7 @@ def wrapper(): return func(space) return wrapper - monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper) + monkeypatch.setattr(pypy.module.cpyext.gateway, 'make_wrapper', make_wrapper) @specialize.memo() def get_tp_function(space, typedef): Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/thread.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/thread.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/thread.py Wed Jun 9 17:56:49 2010 @@ -1,6 +1,6 @@ from pypy.module.thread import ll_thread -from pypy.module.cpyext.api import CANNOT_FAIL, cpython_api +from pypy.module.cpyext.gateway import CANNOT_FAIL, cpython_api from pypy.rpython.lltypesystem import rffi @cpython_api([], rffi.LONG, error=CANNOT_FAIL) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/tupleobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/tupleobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/tupleobject.py Wed Jun 9 17:56:49 2010 @@ -1,9 +1,9 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL, - build_type_checkers) -from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef, - borrow_from, make_ref, from_ref) +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL +from pypy.module.cpyext.api import Py_ssize_t, build_type_checkers +from pypy.module.cpyext.pyobject import ( + PyObject, PyObjectP, Py_DecRef, borrow_from, make_ref, from_ref) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall from pypy.objspace.std.tupleobject import W_TupleObject Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/typeobject.py Wed Jun 9 17:56:49 2010 @@ -6,11 +6,13 @@ from pypy.interpreter.baseobjspace import DescrMismatch from pypy.objspace.std.typeobject import W_TypeObject, _CPYTYPE from pypy.interpreter.typedef import GetSetProperty +from pypy.module.cpyext.gateway import ( + cpython_api, generic_cpy_call, CANNOT_FAIL) from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, - generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING, - Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL, - PyBufferProcs, build_type_checkers) + cpython_struct, build_type_checkers, bootstrap_function, + Py_ssize_t, PyBufferProcs, Py_TPFLAGS_READY, Py_TPFLAGS_READYING, + Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS) + from pypy.module.cpyext.pyobject import ( PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr, track_reference, RefcountState, borrow_from) Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/unicodeobject.py Wed Jun 9 17:56:49 2010 @@ -1,10 +1,10 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.unicodedata import unicodedb_4_1_0 as unicodedb +from pypy.module.cpyext.gateway import cpython_api, CANNOT_FAIL from pypy.module.cpyext.api import ( - CANNOT_FAIL, Py_ssize_t, build_type_checkers, cpython_api, - bootstrap_function, PyObjectFields, cpython_struct, CONST_STRING, - CONST_WSTRING) + cpython_struct, build_type_checkers, bootstrap_function, + PyObjectFields, Py_ssize_t, CONST_STRING, CONST_WSTRING) from pypy.module.cpyext.pyerrors import PyErr_BadArgument from pypy.module.cpyext.pyobject import PyObject, from_ref, make_typedescr from pypy.module.sys.interp_encoding import setdefaultencoding Modified: pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/weakrefobject.py ============================================================================== --- pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/weakrefobject.py (original) +++ pypy/branch/cpyext-init-cleanup/pypy/module/cpyext/weakrefobject.py Wed Jun 9 17:56:49 2010 @@ -1,4 +1,4 @@ -from pypy.module.cpyext.api import cpython_api +from pypy.module.cpyext.gateway import cpython_api from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.module._weakref.interp__weakref import W_Weakref From arigo at codespeak.net Wed Jun 9 18:24:27 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 18:24:27 +0200 (CEST) Subject: [pypy-svn] r75238 - in pypy/trunk/pypy/module/sys: . test Message-ID: <20100609162427.7FE23282BD6@codespeak.net> Author: arigo Date: Wed Jun 9 18:24:25 2010 New Revision: 75238 Modified: pypy/trunk/pypy/module/sys/app.py pypy/trunk/pypy/module/sys/test/test_sysmodule.py Log: Try to be really careful in sys.excepthook(). Modified: pypy/trunk/pypy/module/sys/app.py ============================================================================== --- pypy/trunk/pypy/module/sys/app.py (original) +++ pypy/trunk/pypy/module/sys/app.py Wed Jun 9 18:24:25 2010 @@ -7,8 +7,35 @@ def excepthook(exctype, value, traceback): """Handle an exception by displaying it with a traceback on sys.stderr.""" - from traceback import print_exception - print_exception(exctype, value, traceback) + try: + from traceback import print_exception + print_exception(exctype, value, traceback) + except: + if not excepthook_failsafe(exctype, value): + raise + +def excepthook_failsafe(exctype, value): + # This version carefully tries to handle all bad cases (e.g. an + # ImportError looking for traceback.py), but may still raise. + # If it does, we get "Error calling sys.excepthook" from app_main.py. + try: + # first try to print the exception's class name + stderr = sys.stderr + stderr.write(getattr(exctype, '__name__', exctype)) + # then attempt to get the str() of the exception + try: + s = str(value) + except: + s = '' + # then print it, and don't worry too much about the extra space + # between the exception class and the ':' + if s: + stderr.write(': %s\n' % (s,)) + else: + stderr.write('\n') + return True # successfully printed at least the class and value + except: + return False # got an exception again... ignore, report the original def exit(exitcode=0): """Exit the interpreter by raising SystemExit(exitcode). Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/trunk/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/trunk/pypy/module/sys/test/test_sysmodule.py Wed Jun 9 18:24:25 2010 @@ -177,6 +177,26 @@ sys.stderr = savestderr assert err.getvalue().endswith("ValueError: 42\n") + def test_excepthook_failsafe_path(self): + import traceback + original_print_exception = traceback.print_exception + import cStringIO + savestderr = sys.stderr + err = cStringIO.StringIO() + sys.stderr = err + try: + traceback.print_exception = "foo" + eh = sys.__excepthook__ + try: + raise ValueError(42) + except ValueError, exc: + eh(*sys.exc_info()) + finally: + traceback.print_exception = original_print_exception + sys.stderr = savestderr + + assert err.getvalue() == "ValueError: 42\n" + # FIXME: testing the code for a lost or replaced excepthook in # Python/pythonrun.c::PyErr_PrintEx() is tricky. From arigo at codespeak.net Wed Jun 9 21:04:06 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jun 2010 21:04:06 +0200 (CEST) Subject: [pypy-svn] r75239 - pypy/trunk/pypy/module/zipimport/test Message-ID: <20100609190406.3A60B282BD6@codespeak.net> Author: arigo Date: Wed Jun 9 21:03:24 2010 New Revision: 75239 Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: This test fails on pypy but passes on CPython. Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Wed Jun 9 21:03:24 2010 @@ -204,6 +204,19 @@ assert mod.__path__ == [self.zipfile + "/xxuuu"] assert mod.yy.f(3) == 3 + def test_package_bug(self): + import os, sys + import new + mod = new.module('xxuuv') + mod.__path__ = [self.zipfile + '/xxuuv'] + sys.modules['xxuuv'] = mod + # + self.writefile(self, "xxuuv/__init__.py", "") + self.writefile(self, "xxuuv/yy.py", "def f(x): return x") + mod = __import__("xxuuv.yy", globals(), locals(), ['__doc__']) + assert mod.__file__ == self.zipfile + "/xxuuv/yy.py" + assert mod.f(3) == 3 + def test_functions(self): import os import zipimport From hpk at codespeak.net Thu Jun 10 09:50:25 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 10 Jun 2010 09:50:25 +0200 (CEST) Subject: [pypy-svn] r75240 - pypy/trunk/py/_code Message-ID: <20100610075025.E53BD282BD6@codespeak.net> Author: hpk Date: Thu Jun 10 09:50:23 2010 New Revision: 75240 Modified: pypy/trunk/py/_code/_assertionold.py Log: defer compilation to frame.eval so that pypy can override and compile to bytecode on its own Modified: pypy/trunk/py/_code/_assertionold.py ============================================================================== --- pypy/trunk/py/_code/_assertionold.py (original) +++ pypy/trunk/py/_code/_assertionold.py Thu Jun 10 09:50:23 2010 @@ -185,10 +185,9 @@ expr2.eval(frame) self.explanation = "%s %s %s" % ( expr.explanation, operation, expr2.explanation) - co = compile("__exprinfo_left %s __exprinfo_right" % operation, - '?', 'eval') + source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(co, __exprinfo_left=expr.result, + self.result = frame.eval(source, __exprinfo_left=expr.result, __exprinfo_right=expr2.result) except passthroughex: raise From afa at codespeak.net Thu Jun 10 10:27:30 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 10:27:30 +0200 (CEST) Subject: [pypy-svn] r75241 - pypy/trunk/py/_code Message-ID: <20100610082730.31FDF282BD6@codespeak.net> Author: afa Date: Thu Jun 10 10:27:28 2010 New Revision: 75241 Modified: pypy/trunk/py/_code/_assertionold.py Log: When building the explanation of failed assertions, don't compile() code ourselves, but pass the source to frame.eval(). This helps when running AppTests with cpython2.7, where the opcodes as incompatible with the pypy interpreter. I could not convert the calls to pycodegen, but I'm not sure what they are useful for. Modified: pypy/trunk/py/_code/_assertionold.py ============================================================================== --- pypy/trunk/py/_code/_assertionold.py (original) +++ pypy/trunk/py/_code/_assertionold.py Thu Jun 10 10:27:28 2010 @@ -138,28 +138,28 @@ __view__ = ast.Name def is_local(self, frame): - co = compile('%r in locals() is not globals()' % self.name, '?', 'eval') + source = '%r in locals() is not globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_global(self, frame): - co = compile('%r in globals()' % self.name, '?', 'eval') + source = '%r in globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_builtin(self, frame): - co = compile('%r not in locals() and %r not in globals()' % ( - self.name, self.name), '?', 'eval') + source = '%r not in locals() and %r not in globals()' % ( + self.name, self.name) try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: @@ -187,8 +187,9 @@ expr.explanation, operation, expr2.explanation) source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(source, __exprinfo_left=expr.result, - __exprinfo_right=expr2.result) + self.result = frame.eval(source, + __exprinfo_left=expr.result, + __exprinfo_right=expr2.result) except passthroughex: raise except: @@ -234,14 +235,14 @@ class UnaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): expr = Interpretable(self.expr) expr.eval(frame) self.explanation = astpattern.replace('__exprinfo_expr', expr.explanation) try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(astpattern, + __exprinfo_expr=expr.result) except passthroughex: raise except: @@ -262,8 +263,7 @@ class BinaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): left = Interpretable(self.left) left.eval(frame) right = Interpretable(self.right) @@ -272,8 +272,9 @@ .replace('__exprinfo_left', left .explanation) .replace('__exprinfo_right', right.explanation)) try: - self.result = frame.eval(co, __exprinfo_left=left.result, - __exprinfo_right=right.result) + self.result = frame.eval(astpattern, + __exprinfo_left=left.result, + __exprinfo_right=right.result) except passthroughex: raise except: @@ -286,9 +287,10 @@ __view__ = ast.CallFunc def is_bool(self, frame): - co = compile('isinstance(__exprinfo_value, bool)', '?', 'eval') + source = 'isinstance(__exprinfo_value, bool)' try: - return frame.is_true(frame.eval(co, __exprinfo_value=self.result)) + return frame.is_true(frame.eval(source, + __exprinfo_value=self.result)) except passthroughex: raise except: @@ -335,9 +337,8 @@ if source.endswith(','): source = source[:-1] source += ')' - co = compile(source, '?', 'eval') try: - self.result = frame.eval(co, **vars) + self.result = frame.eval(source, **vars) except passthroughex: raise except: @@ -352,21 +353,20 @@ def eval(self, frame): expr = Interpretable(self.expr) expr.eval(frame) - co = compile('__exprinfo_expr.%s' % self.attrname, '?', 'eval') + source = '__exprinfo_expr.%s' % self.attrname try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(source, __exprinfo_expr=expr.result) except passthroughex: raise except: raise Failure(self) self.explanation = '%s.%s' % (expr.explanation, self.attrname) # if the attribute comes from the instance, its value is interesting - co = compile('hasattr(__exprinfo_expr, "__dict__") and ' - '%r in __exprinfo_expr.__dict__' % self.attrname, - '?', 'eval') + source = ('hasattr(__exprinfo_expr, "__dict__") and ' + '%r in __exprinfo_expr.__dict__' % self.attrname) try: from_instance = frame.is_true( - frame.eval(co, __exprinfo_expr=expr.result)) + frame.eval(source, __exprinfo_expr=expr.result)) except passthroughex: raise except: From afa at codespeak.net Thu Jun 10 14:23:35 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 14:23:35 +0200 (CEST) Subject: [pypy-svn] r75244 - in pypy/trunk/pypy/module/zipimport: . test Message-ID: <20100610122335.D06C3282BD6@codespeak.net> Author: afa Date: Thu Jun 10 14:23:34 2010 New Revision: 75244 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: Fix tests in zipimport module. Usage of os.path.sep is needed on Windows. Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Thu Jun 10 14:23:34 2010 @@ -146,7 +146,7 @@ def import_py_file(self, space, modname, filename, buf, pkgpath): w = space.wrap w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) code_w = importing.parse_source_module(space, filename, buf) @@ -193,7 +193,7 @@ pkgpath) buf = buf[8:] # XXX ugly copy, should use sequential read instead w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) result = importing.load_compiled_module(space, w(modname), w_mod, Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Thu Jun 10 14:23:34 2010 @@ -202,6 +202,9 @@ self.writefile(self, "xxuuu/yy.py", "def f(x): return x") mod = __import__("xxuuu", globals(), locals(), ['yy']) assert mod.__path__ == [self.zipfile + "/xxuuu"] + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuu" + os.path.sep + + "__init__.py") assert mod.yy.f(3) == 3 def test_package_bug(self): @@ -214,7 +217,9 @@ self.writefile(self, "xxuuv/__init__.py", "") self.writefile(self, "xxuuv/yy.py", "def f(x): return x") mod = __import__("xxuuv.yy", globals(), locals(), ['__doc__']) - assert mod.__file__ == self.zipfile + "/xxuuv/yy.py" + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuv" + os.path.sep + + "yy.py") assert mod.f(3) == 3 def test_functions(self): From afa at codespeak.net Thu Jun 10 14:42:14 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 14:42:14 +0200 (CEST) Subject: [pypy-svn] r75245 - pypy/trunk/pypy/module/zipimport/test Message-ID: <20100610124214.512F2282BD6@codespeak.net> Author: afa Date: Thu Jun 10 14:42:13 2010 New Revision: 75245 Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: Add a test for the change in import_pyc_file() Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Thu Jun 10 14:42:13 2010 @@ -222,6 +222,22 @@ + "yy.py") assert mod.f(3) == 3 + def test_pyc_in_package(self): + import os, sys + import new + mod = new.module('xxuuw') + mod.__path__ = [self.zipfile + '/xxuuw'] + sys.modules['xxuuw'] = mod + # + self.writefile(self, "xxuuw/__init__.py", "") + self.writefile(self, "xxuuw/zz.pyc", self.test_pyc) + mod = __import__("xxuuw.zz", globals(), locals(), ['__doc__']) + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuw" + os.path.sep + + "zz.pyc") + assert mod.get_file() == mod.__file__ + assert mod.get_name() == mod.__name__ + def test_functions(self): import os import zipimport From arigo at codespeak.net Thu Jun 10 14:43:11 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jun 2010 14:43:11 +0200 (CEST) Subject: [pypy-svn] r75246 - pypy/branch/multijit-3 Message-ID: <20100610124311.6457F282BD6@codespeak.net> Author: arigo Date: Thu Jun 10 14:43:10 2010 New Revision: 75246 Added: pypy/branch/multijit-3/ - copied from r75245, pypy/trunk/ Log: Another attempt at finishing branch/multijit-2. From afa at codespeak.net Thu Jun 10 14:46:11 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 14:46:11 +0200 (CEST) Subject: [pypy-svn] r75247 - in pypy/trunk/pypy/module/zipimport: . test Message-ID: <20100610124611.380A0282BD6@codespeak.net> Author: afa Date: Thu Jun 10 14:46:09 2010 New Revision: 75247 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: Change the test so that is passes on CPython with the "-A" option. Fix pypy implementation accordingly. Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Thu Jun 10 14:46:09 2010 @@ -242,7 +242,7 @@ pass else: if is_package: - pkgpath = self.name + '/' + filename + pkgpath = self.name + os.path.sep + filename else: pkgpath = None try: Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Thu Jun 10 14:46:09 2010 @@ -201,7 +201,7 @@ self.writefile(self, "xxuuu/__init__.py", "") self.writefile(self, "xxuuu/yy.py", "def f(x): return x") mod = __import__("xxuuu", globals(), locals(), ['yy']) - assert mod.__path__ == [self.zipfile + "/xxuuu"] + assert mod.__path__ == [self.zipfile + os.path.sep + "xxuuu"] assert mod.__file__ == (self.zipfile + os.path.sep + "xxuuu" + os.path.sep + "__init__.py") From afa at codespeak.net Thu Jun 10 15:42:56 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 15:42:56 +0200 (CEST) Subject: [pypy-svn] r75250 - pypy/trunk/pypy/module/zipimport/test Message-ID: <20100610134256.F0E5E282BD6@codespeak.net> Author: afa Date: Thu Jun 10 15:42:55 2010 New Revision: 75250 Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: A test that works on top of CPython (with -A) but fails with pypy. Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Thu Jun 10 15:42:55 2010 @@ -118,6 +118,18 @@ finally: del _zip_directory_cache[self.zipfile] + def test_cache_subdir(self): + self.writefile(self, 'x.py', '') + self.writefile(self, 'sub/__init__.py', '') + self.writefile(self, 'sub/yy.py', '') + from zipimport import _zip_directory_cache, zipimporter + sub_importer = zipimporter(self.zipfile + '/sub') + main_importer = zipimporter(self.zipfile) + + assert main_importer is not sub_importer + assert main_importer.prefix == "" + assert sub_importer.prefix == "sub\\" + def test_good_bad_arguments(self): from zipimport import zipimporter import os From afa at codespeak.net Thu Jun 10 19:09:26 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 10 Jun 2010 19:09:26 +0200 (CEST) Subject: [pypy-svn] r75251 - in pypy/trunk/pypy/module/cpyext: . include Message-ID: <20100610170926.CFA80282BD6@codespeak.net> Author: afa Date: Thu Jun 10 19:09:21 2010 New Revision: 75251 Added: pypy/trunk/pypy/module/cpyext/include/modsupport.inl (contents, props changed) Modified: pypy/trunk/pypy/module/cpyext/include/Python.h pypy/trunk/pypy/module/cpyext/modsupport.py Log: Be sure to refuse extension modules built with CPython: pypy-c does not define the Py_InitModule4 symbol anymore, it exposes _Py_InitPyPyModule() instead, and our Python.h takes care to redirect calls. Next step: see if we can catch the error message and turn it into a friendly ImportError. Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Thu Jun 10 19:09:21 2010 @@ -104,6 +104,8 @@ #include +#include "modsupport.inl" + /* Define macros for inline documentation. */ #define PyDoc_VAR(name) static char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) Added: pypy/trunk/pypy/module/cpyext/include/modsupport.inl ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/cpyext/include/modsupport.inl Thu Jun 10 19:09:21 2010 @@ -0,0 +1,21 @@ +/* -*- C -*- */ +/* Module support interface */ + +#ifndef Py_MODSUPPORT_INL +#define Py_MODSUPPORT_INL +#ifdef __cplusplus +extern "C" { +#endif + +Py_LOCAL_INLINE(PyObject *) Py_InitModule4( + const char* name, PyMethodDef* methods, + const char* doc, PyObject *self, + int api_version) +{ + return _Py_InitPyPyModule(name, methods, doc, self, api_version); +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MODSUPPORT_INL */ Modified: pypy/trunk/pypy/module/cpyext/modsupport.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/modsupport.py (original) +++ pypy/trunk/pypy/module/cpyext/modsupport.py Thu Jun 10 19:09:21 2010 @@ -31,9 +31,12 @@ return w_mod +# This is actually the Py_InitModule4 function, +# renamed to refuse modules built against CPython headers. +# The implementation of Py_InitModule4 is in include/modsupport.inl @cpython_api([CONST_STRING, lltype.Ptr(PyMethodDef), CONST_STRING, PyObject, rffi.INT_real], PyObject) -def Py_InitModule4(space, name, methods, doc, w_self, apiver): +def _Py_InitPyPyModule(space, name, methods, doc, w_self, apiver): """ Create a new module object based on a name and table of functions, returning the new module object. If doc is non-NULL, it will be used to define the From benjamin at codespeak.net Thu Jun 10 20:50:14 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 10 Jun 2010 20:50:14 +0200 (CEST) Subject: [pypy-svn] r75252 - pypy/trunk/py/_code Message-ID: <20100610185014.E5CD0282BD6@codespeak.net> Author: benjamin Date: Thu Jun 10 20:50:12 2010 New Revision: 75252 Modified: pypy/trunk/py/_code/_assertionnew.py Log: fix assertion interpretation with pow Modified: pypy/trunk/py/_code/_assertionnew.py ============================================================================== --- pypy/trunk/py/_code/_assertionnew.py (original) +++ pypy/trunk/py/_code/_assertionnew.py Thu Jun 10 20:50:12 2010 @@ -92,6 +92,7 @@ ast.LtE : "<=", ast.Gt : ">", ast.GtE : ">=", + ast.Pow : "**", ast.Is : "is", ast.IsNot : "is not", ast.In : "in", From fijal at codespeak.net Fri Jun 11 01:57:11 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jun 2010 01:57:11 +0200 (CEST) Subject: [pypy-svn] r75253 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20100610235711.DE3AA282B90@codespeak.net> Author: fijal Date: Fri Jun 11 01:57:09 2010 New Revision: 75253 Modified: pypy/build/bot2/pypybuildbot/builds.py pypy/build/bot2/pypybuildbot/test/test_builds.py Log: An attempt to upload files into branch-related directories Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 11 01:57:09 2010 @@ -1,5 +1,5 @@ from buildbot.process import factory -from buildbot.steps import source, shell, transfer +from buildbot.steps import source, shell, transfer, master from buildbot.status.builder import SUCCESS from buildbot.process.properties import WithProperties import os @@ -12,6 +12,21 @@ return self.describe(True) + ['aborted'] return shell.ShellCommand.getText(self, cmd, results) +class PyPyUpload(transfer.FileUpload): + parms = transfer.FileUpload.parms + ['basename'] + + def start(self): + properties = self.build.getProperties() + branch = properties['branch'] + if branch is None: + branch = 'trunk' + masterdest = properties.render(self.masterdest) + masterdest = os.path.expanduser(masterdest) + masterdest = os.path.join(masterdest, branch) + os.makedirs(masterdest) + masterdest = os.path.join(masterdest, self.basename) + self.masterdest = masterdest + transfer.FileUpload.start(self) class Translate(ShellCmd): name = "translate" @@ -127,12 +142,14 @@ kind = 'stackless' else: kind = 'nojit' - nightly = os.path.expanduser('~/nightly/pypy-c-' + kind + '-%(got_revision)s-' + platform + '.bz2') + nightly = '~/nightly/' + name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + '.bz2' pypy_c_rel = 'build/pypy/translator/goal/pypy-c.bz2' - self.addStep(transfer.FileUpload(slavesrc=pypy_c_rel, - masterdest=WithProperties(nightly), - workdir='.', - blocksize=100*1024)) + self.addStep(PyPyUpload(slavesrc=pypy_c_rel, + masterdest=WithProperties(nightly), + basename=name, + workdir='.', + blocksize=100*1024)) class JITBenchmark(factory.BuildFactory): Modified: pypy/build/bot2/pypybuildbot/test/test_builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_builds.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_builds.py Fri Jun 11 01:57:09 2010 @@ -1,6 +1,11 @@ +import py from pypybuildbot import builds class FakeProperties(object): + def __getitem__(self, item): + if item == 'branch': + return None + def render(self, x): return x @@ -10,6 +15,19 @@ def getProperties(self): return FakeProperties() + def getSlaveCommandVersion(self, *args): + return 3 + +class FakeStepStatus(object): + def setText(self, *args): + pass + +class FakeDeferred(object): + def addCallback(self, *args): + return FakeDeferred() + def addErrback(self, *args): + return FakeDeferred() + def test_Translate(): expected = ['translate.py', '--batch', '-O0', 'targetpypystandalone', '--no-allworkingmodules'] @@ -26,3 +44,16 @@ rebuiltTranslate.build = FakePropertyBuilder() rebuiltTranslate.startCommand = lambda *args: None rebuiltTranslate.start() + +def test_pypy_upload(): + pth = py.test.ensuretemp('buildbot') + inst = builds.PyPyUpload(slavesrc='slavesrc', masterdest=str(pth.join('mstr')), + basename='base', workdir='.', + blocksize=100) + factory, kw = inst.factory + rebuilt = factory(**kw) + rebuilt.build = FakePropertyBuilder() + rebuilt.step_status = FakeStepStatus() + rebuilt.runCommand = lambda *args: FakeDeferred() + rebuilt.start() + assert pth.join('mstr').check(dir=True) From fijal at codespeak.net Fri Jun 11 02:17:21 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jun 2010 02:17:21 +0200 (CEST) Subject: [pypy-svn] r75254 - pypy/build/bot2/pypybuildbot Message-ID: <20100611001721.6D849282B90@codespeak.net> Author: fijal Date: Fri Jun 11 02:17:19 2010 New Revision: 75254 Modified: pypy/build/bot2/pypybuildbot/master.py Log: Use different platform for 64bit, to differentiate a nightly build Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Fri Jun 11 02:17:19 2010 @@ -57,6 +57,9 @@ pypyTranslatedAppLevelTestFactory = pypybuilds.Translated(lib_python=True, app_tests=True) +pypyTranslatedAppLevelTestFactory64 = pypybuilds.Translated(lib_python=True, + app_tests=True, + platform='linux64') pypyStacklessTranslatedAppLevelTestFactory = pypybuilds.Translated( translationArgs=["-O2", "--stackless"], targetArgs=[], @@ -175,7 +178,7 @@ {"name": APPLVLLINUX64, "slavenames": ["tannit64"], "builddir": APPLVLLINUX64, - "factory": pypyTranslatedAppLevelTestFactory, + "factory": pypyTranslatedAppLevelTestFactory64, "category": "applevel64" }, {"name": STACKLESSAPPLVLLINUX32, From fijal at codespeak.net Fri Jun 11 02:20:45 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jun 2010 02:20:45 +0200 (CEST) Subject: [pypy-svn] r75255 - pypy/release/1.2.1.x Message-ID: <20100611002045.D934C282B90@codespeak.net> Author: fijal Date: Fri Jun 11 02:20:42 2010 New Revision: 75255 Removed: pypy/release/1.2.1.x/ Log: Remove this, we're not doing 1.2.1 From fijal at codespeak.net Fri Jun 11 02:21:23 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jun 2010 02:21:23 +0200 (CEST) Subject: [pypy-svn] r75256 - pypy/release/1.3.x Message-ID: <20100611002123.6E53D282B90@codespeak.net> Author: fijal Date: Fri Jun 11 02:21:21 2010 New Revision: 75256 Added: pypy/release/1.3.x/ (props changed) - copied from r75255, pypy/trunk/ Log: Create a new branch for the release From afa at codespeak.net Fri Jun 11 09:50:14 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 09:50:14 +0200 (CEST) Subject: [pypy-svn] r75257 - pypy/trunk/pypy/translator/c/src Message-ID: <20100611075014.15024282B90@codespeak.net> Author: afa Date: Fri Jun 11 09:50:11 2010 New Revision: 75257 Modified: pypy/trunk/pypy/translator/c/src/commondefs.h Log: Avoid a compilation warning on Windows Modified: pypy/trunk/pypy/translator/c/src/commondefs.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/commondefs.h (original) +++ pypy/trunk/pypy/translator/c/src/commondefs.h Fri Jun 11 09:50:11 2010 @@ -82,5 +82,7 @@ #define Py_HUGE_VAL HUGE_VAL #ifdef _WIN32 +#ifndef MS_WINDOWS # define MS_WINDOWS /* a synonym */ #endif +#endif From antocuni at codespeak.net Fri Jun 11 10:48:13 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 10:48:13 +0200 (CEST) Subject: [pypy-svn] r75258 - pypy/branch/sys-prefix/pypy/translator Message-ID: <20100611084813.EF7C4282B90@codespeak.net> Author: antocuni Date: Fri Jun 11 10:48:11 2010 New Revision: 75258 Modified: pypy/branch/sys-prefix/pypy/translator/geninterplevel.py Log: tentatively comment out this code. I could not find any test that fails because of this, we will see if any fails in the nightly run Modified: pypy/branch/sys-prefix/pypy/translator/geninterplevel.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/geninterplevel.py (original) +++ pypy/branch/sys-prefix/pypy/translator/geninterplevel.py Fri Jun 11 10:48:11 2010 @@ -496,21 +496,22 @@ need_extra_path = True name = self.uniquename('mod_%s' % value.__name__) if need_extra_path: - self.initcode.append1('import pypy') - self.initcode.append1('import sys') - self.initcode.append1('import os') - self.initcode.append1('for pkgdir in pypy.__path__:\n' - ' libdir = os.path.join(pkgdir, "lib")\n' - ' if os.path.isdir(libdir):\n' - ' break\n' - 'else:\n' - ' raise Exception, "cannot find pypy/lib directory"\n' - 'sys.path.insert(0, libdir)\n') - self.initcode.append1('try:\n' - ' import %s as _tmp\n' - 'finally:\n' - ' if libdir in sys.path:\n' - ' sys.path.remove(libdir)\n' % value.__name__) + assert False + ## self.initcode.append1('import pypy') + ## self.initcode.append1('import sys') + ## self.initcode.append1('import os') + ## self.initcode.append1('for pkgdir in pypy.__path__:\n' + ## ' libdir = os.path.join(pkgdir, "lib")\n' + ## ' if os.path.isdir(libdir):\n' + ## ' break\n' + ## 'else:\n' + ## ' raise Exception, "cannot find pypy/lib directory"\n' + ## 'sys.path.insert(0, libdir)\n') + ## self.initcode.append1('try:\n' + ## ' import %s as _tmp\n' + ## 'finally:\n' + ## ' if libdir in sys.path:\n' + ## ' sys.path.remove(libdir)\n' % value.__name__) else: self.initcode.append1('import %s as _tmp' % value.__name__) self.initcode.append1('%s = space.wrap(_tmp)' % (name)) From afa at codespeak.net Fri Jun 11 11:17:29 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 11:17:29 +0200 (CEST) Subject: [pypy-svn] r75259 - pypy/trunk/pypy/module/cpyext/include Message-ID: <20100611091729.74A6D282B90@codespeak.net> Author: afa Date: Fri Jun 11 11:17:27 2010 New Revision: 75259 Modified: pypy/trunk/pypy/module/cpyext/include/modsupport.inl Log: Two workarounds to fix the compilation errors in translation. Modified: pypy/trunk/pypy/module/cpyext/include/modsupport.inl ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/modsupport.inl (original) +++ pypy/trunk/pypy/module/cpyext/include/modsupport.inl Fri Jun 11 11:17:27 2010 @@ -7,12 +7,20 @@ extern "C" { #endif +#ifdef PYPY_STANDALONE +/* XXX1 On translation, forwarddecl.h is included after this file */ +/* XXX2 genc.py transforms "const char*" into "char*" */ +extern PyObject *_Py_InitPyPyModule(char *, PyMethodDef *, char *, PyObject *, int); +#endif + Py_LOCAL_INLINE(PyObject *) Py_InitModule4( const char* name, PyMethodDef* methods, const char* doc, PyObject *self, int api_version) { - return _Py_InitPyPyModule(name, methods, doc, self, api_version); + return _Py_InitPyPyModule((char*)name, methods, + (char*)doc, self, + api_version); } #ifdef __cplusplus From afa at codespeak.net Fri Jun 11 11:24:59 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 11:24:59 +0200 (CEST) Subject: [pypy-svn] r75260 - pypy/trunk/pypy/translator/platform Message-ID: <20100611092459.CC69B282B90@codespeak.net> Author: afa Date: Fri Jun 11 11:24:58 2010 New Revision: 75260 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: Fix generated makefile on Windows. it compiles now, but it's not correct: - most cpyext API functions are not exported - jit support is probably broken Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Fri Jun 11 11:24:58 2010 @@ -267,7 +267,8 @@ ]) if shared: - m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename), + m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename) + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo ' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' From arigo at codespeak.net Fri Jun 11 11:52:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 11:52:44 +0200 (CEST) Subject: [pypy-svn] r75261 - in pypy/branch/multijit-3/pypy/jit/codewriter: . test Message-ID: <20100611095244.4296A282B90@codespeak.net> Author: arigo Date: Fri Jun 11 11:52:42 2010 New Revision: 75261 Modified: pypy/branch/multijit-3/pypy/jit/codewriter/call.py pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py pypy/branch/multijit-3/pypy/jit/codewriter/test/test_call.py pypy/branch/multijit-3/pypy/jit/codewriter/test/test_codewriter.py pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py Log: Fix codewriter to do (in a single pass) the transformation for multiple JitDrivers. Modified: pypy/branch/multijit-3/pypy/jit/codewriter/call.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/call.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/call.py Fri Jun 11 11:52:42 2010 @@ -16,21 +16,22 @@ class CallControl(object): virtualref_info = None # optionally set from outside - virtualizable_info = None # optionally set from outside - portal_runner_ptr = None # optionally set from outside - def __init__(self, cpu=None, portal_graph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): + assert isinstance(jitdrivers_sd, list) # debugging self.cpu = cpu - self.portal_graph = portal_graph + self.jitdrivers_sd = jitdrivers_sd self.jitcodes = {} # map {graph: jitcode} self.unfinished_graphs = [] # list of graphs with pending jitcodes - self.jitdriver = None if hasattr(cpu, 'rtyper'): # for tests self.rtyper = cpu.rtyper translator = self.rtyper.annotator.translator self.raise_analyzer = RaiseAnalyzer(translator) self.readwrite_analyzer = ReadWriteAnalyzer(translator) self.virtualizable_analyzer = VirtualizableAnalyzer(translator) + # + for index, jd in enumerate(jitdrivers_sd): + jd.index = index def find_all_graphs(self, policy): try: @@ -41,8 +42,8 @@ def is_candidate(graph): return policy.look_inside_graph(graph) - assert self.portal_graph is not None - todo = [self.portal_graph] + assert len(self.jitdrivers_sd) > 0 + todo = [jd.portal_graph for jd in self.jitdrivers_sd] if hasattr(self, 'rtyper'): for oopspec_name, ll_args, ll_res in support.inline_calls_to: c_func, _ = support.builtin_func_for_spec(self.rtyper, @@ -122,7 +123,7 @@ def guess_call_kind(self, op, is_candidate=None): if op.opname == 'direct_call': funcptr = op.args[0].value - if funcptr is self.portal_runner_ptr: + if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None: return 'recursive' funcobj = get_funcobj(funcptr) if getattr(funcobj, 'graph', None) is None: @@ -143,6 +144,10 @@ # used only after find_all_graphs() return graph in self.candidate_graphs + def grab_initial_jitcodes(self): + for jd in self.jitdrivers_sd: + jd.mainjitcode = self.get_jitcode(jd.portal_graph) + def enum_pending_graphs(self): while self.unfinished_graphs: graph = self.unfinished_graphs.pop() @@ -241,12 +246,26 @@ return (effectinfo is None or effectinfo.extraeffect >= EffectInfo.EF_CAN_RAISE) - def found_jitdriver(self, jitdriver): - if self.jitdriver is None: - self.jitdriver = jitdriver - else: - assert self.jitdriver is jitdriver + def jitdriver_sd_from_portal_graph(self, graph): + for jd in self.jitdrivers_sd: + if jd.portal_graph is graph: + return jd + return None - def getjitdriver(self): - assert self.jitdriver is not None, "order dependency issue?" - return self.jitdriver + def jitdriver_sd_from_portal_runner_ptr(self, funcptr): + for jd in self.jitdrivers_sd: + if funcptr is jd.portal_runner_ptr: + return jd + return None + + def get_vinfo(self, VTYPEPTR): + seen = set() + for jd in self.jitdrivers_sd: + if jd.virtualizable_info is not None: + if jd.virtualizable_info.is_vtypeptr(VTYPEPTR): + seen.add(jd.virtualizable_info) + if seen: + assert len(seen) == 1 + return seen.pop() + else: + return None Modified: pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py Fri Jun 11 11:52:42 2010 @@ -14,29 +14,30 @@ class CodeWriter(object): callcontrol = None # for tests - def __init__(self, cpu=None, maingraph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): self.cpu = cpu self.assembler = Assembler() - self.portal_graph = maingraph - self.callcontrol = CallControl(cpu, maingraph) + self.callcontrol = CallControl(cpu, jitdrivers_sd) + self._seen_files = set() def transform_func_to_jitcode(self, func, values, type_system='lltype'): """For testing.""" rtyper = support.annotate(func, values, type_system=type_system) graph = rtyper.annotator.translator.graphs[0] jitcode = JitCode("test") - self.transform_graph_to_jitcode(graph, jitcode, True, True) + self.transform_graph_to_jitcode(graph, jitcode, True) return jitcode - def transform_graph_to_jitcode(self, graph, jitcode, portal, verbose): + def transform_graph_to_jitcode(self, graph, jitcode, verbose): """Transform a graph into a JitCode containing the same bytecode in a different format. """ + portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph) graph = copygraph(graph, shallowvars=True) # # step 1: mangle the graph so that it contains the final instructions # that we want in the JitCode, but still as a control flow graph - transform_graph(graph, self.cpu, self.callcontrol, portal) + transform_graph(graph, self.cpu, self.callcontrol) # # step 2: perform register allocation on it regallocs = {} @@ -59,16 +60,14 @@ self.assembler.assemble(ssarepr, jitcode) # # print the resulting assembler - self.print_ssa_repr(ssarepr, portal, verbose) + self.print_ssa_repr(ssarepr, portal_jd, verbose) def make_jitcodes(self, verbose=False): log.info("making JitCodes...") - maingraph = self.portal_graph - self.mainjitcode = self.callcontrol.get_jitcode(maingraph) + self.callcontrol.grab_initial_jitcodes() count = 0 for graph, jitcode in self.callcontrol.enum_pending_graphs(): - self.transform_graph_to_jitcode(graph, jitcode, - graph is maingraph, verbose) + self.transform_graph_to_jitcode(graph, jitcode, verbose) count += 1 if not count % 500: log.info("Produced %d jitcodes" % count) @@ -76,33 +75,35 @@ log.info("there are %d JitCode instances." % count) def setup_vrefinfo(self, vrefinfo): + # must be called at most once + assert self.callcontrol.virtualref_info is None self.callcontrol.virtualref_info = vrefinfo - def setup_virtualizable_info(self, vinfo): - self.callcontrol.virtualizable_info = vinfo - - def setup_portal_runner_ptr(self, portal_runner_ptr): - self.callcontrol.portal_runner_ptr = portal_runner_ptr + def setup_jitdriver(self, jitdriver_sd): + # Must be called once per jitdriver. Usually jitdriver_sd is an + # instance of pypy.jit.metainterp.jitdriver.JitDriverStaticData. + self.callcontrol.jitdrivers_sd.append(jitdriver_sd) def find_all_graphs(self, policy): return self.callcontrol.find_all_graphs(policy) - def print_ssa_repr(self, ssarepr, portal, verbose): + def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose): if verbose: print '%s:' % (ssarepr.name,) print format_assembler(ssarepr) else: dir = udir.ensure("jitcodes", dir=1) - if portal: - name = "00_portal_runner" + if portal_jitdriver: + name = "%02d_portal_runner" % (portal_jitdriver.index,) elif ssarepr.name and ssarepr.name != '?': name = ssarepr.name else: name = 'unnamed' % id(ssarepr) i = 1 extra = '' - while dir.join(name+extra).check(exists=1): + while name+extra in self._seen_files: i += 1 extra = '.%d' % i + self._seen_files.add(name+extra) dir.join(name+extra).write(format_assembler(ssarepr)) log.dot() Modified: pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py Fri Jun 11 11:52:42 2010 @@ -13,12 +13,12 @@ from pypy.translator.simplify import get_funcobj -def transform_graph(graph, cpu=None, callcontrol=None, portal=True): +def transform_graph(graph, cpu=None, callcontrol=None): """Transform a control flow graph to make it suitable for being flattened in a JitCode. """ t = Transformer(cpu, callcontrol) - t.transform(graph, portal) + t.transform(graph) class Transformer(object): @@ -27,9 +27,8 @@ self.cpu = cpu self.callcontrol = callcontrol - def transform(self, graph, portal): + def transform(self, graph): self.graph = graph - self.portal = portal for block in list(graph.iterblocks()): self.optimize_block(block) @@ -317,10 +316,12 @@ return op1 def handle_recursive_call(self, op): - ops = self.promote_greens(op.args[1:]) - targetgraph = self.callcontrol.portal_graph - num_green_args = len(self.callcontrol.getjitdriver().greens) - args = (self.make_three_lists(op.args[1:1+num_green_args]) + + jitdriver_sd = self.callcontrol.jitdriver_sd_from_portal_runner_ptr( + op.args[0]) + ops = self.promote_greens(op.args[1:], jitdriver_sd.jitdriver) + num_green_args = len(jitdriver_sd.jitdriver.greens) + args = ([Constant(jitdriver_sd.index, lltype.Signed)] + + self.make_three_lists(op.args[1:1+num_green_args]) + self.make_three_lists(op.args[1+num_green_args:])) kind = getkind(op.result.concretetype)[0] op0 = SpaceOperation('recursive_call_%s' % kind, args, op.result) @@ -475,14 +476,14 @@ # check for virtualizable try: if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('getfield_vable_%s' % kind, [v_inst, descr], op.result)] - except VirtualizableArrayField: + except VirtualizableArrayField, e: # xxx hack hack hack - vinfo = self.callcontrol.virtualizable_info + vinfo = e.args[1] arrayindex = vinfo.array_field_counter[op.args[1].value] arrayfielddescr = vinfo.array_field_descrs[arrayindex] arraydescr = vinfo.array_descrs[arrayindex] @@ -519,7 +520,7 @@ return # check for virtualizable if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('setfield_vable_%s' % kind, @@ -536,21 +537,23 @@ return (op.args[1].value == 'typeptr' and op.args[0].concretetype.TO._hints.get('typeptr')) + def get_vinfo(self, v_virtualizable): + if self.callcontrol is None: # for tests + return None + return self.callcontrol.get_vinfo(v_virtualizable.concretetype) + def is_virtualizable_getset(self, op): # every access of an object of exactly the type VTYPEPTR is # likely to be a virtualizable access, but we still have to # check it in pyjitpl.py. - try: - vinfo = self.callcontrol.virtualizable_info - except AttributeError: - return False - if vinfo is None or not vinfo.is_vtypeptr(op.args[0].concretetype): + vinfo = self.get_vinfo(op.args[0]) + if vinfo is None: return False res = False if op.args[1].value in vinfo.static_field_to_extra_box: res = True if op.args[1].value in vinfo.array_fields: - res = VirtualizableArrayField(self.graph) + res = VirtualizableArrayField(self.graph, vinfo) if res: flags = self.vable_flags[op.args[0]] @@ -560,8 +563,9 @@ raise res return res - def get_virtualizable_field_descr(self, fieldname): - vinfo = self.callcontrol.virtualizable_info + def get_virtualizable_field_descr(self, op): + fieldname = op.args[1].value + vinfo = self.get_vinfo(op.args[0]) index = vinfo.static_field_to_extra_box[fieldname] return vinfo.static_field_descrs[index] @@ -751,9 +755,10 @@ return Constant(value, lltype.Bool) return op - def promote_greens(self, args): + def promote_greens(self, args, jitdriver): ops = [] - num_green_args = len(self.callcontrol.getjitdriver().greens) + num_green_args = len(jitdriver.greens) + assert len(args) == num_green_args + len(jitdriver.reds) for v in args[:num_green_args]: if isinstance(v, Variable) and v.concretetype is not lltype.Void: kind = getkind(v.concretetype) @@ -763,20 +768,19 @@ return ops def rewrite_op_jit_marker(self, op): - self.callcontrol.found_jitdriver(op.args[1].value) key = op.args[0].value - return getattr(self, 'handle_jit_marker__%s' % key)(op) + jitdriver = op.args[1].value + return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver) - def handle_jit_marker__jit_merge_point(self, op): - assert self.portal, "jit_merge_point in non-main graph!" - ops = self.promote_greens(op.args[2:]) - num_green_args = len(self.callcontrol.getjitdriver().greens) + def handle_jit_marker__jit_merge_point(self, op, jitdriver): + ops = self.promote_greens(op.args[2:], jitdriver) + num_green_args = len(jitdriver.greens) args = (self.make_three_lists(op.args[2:2+num_green_args]) + self.make_three_lists(op.args[2+num_green_args:])) op1 = SpaceOperation('jit_merge_point', args, None) return ops + [op1] - def handle_jit_marker__can_enter_jit(self, op): + def handle_jit_marker__can_enter_jit(self, op, jitdriver): return SpaceOperation('can_enter_jit', [], None) def rewrite_op_debug_assert(self, op): @@ -975,9 +979,8 @@ def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables - vinfo = self.callcontrol.virtualizable_info + vinfo = self.get_vinfo(op.args[0]) assert vinfo is not None - assert vinfo.is_vtypeptr(op.args[0].concretetype) self.vable_flags[op.args[0]] = op.args[2].value return [] Modified: pypy/branch/multijit-3/pypy/jit/codewriter/test/test_call.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/test/test_call.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/test/test_call.py Fri Jun 11 11:52:42 2010 @@ -52,13 +52,19 @@ # ____________________________________________________________ +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + def test_find_all_graphs(): def g(x): return x + 2 def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) res = cc.find_all_graphs(FakePolicy()) funcs = set([graph.func for graph in res]) assert funcs == set([f, g]) @@ -69,7 +75,8 @@ def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) class CustomFakePolicy: def look_inside_graph(self, graph): assert graph.name == 'g' @@ -83,10 +90,11 @@ def test_guess_call_kind_and_calls_from_graphs(): class portal_runner_obj: graph = object() + class FakeJitDriverSD: + portal_runner_ptr = portal_runner_obj g = object() g1 = object() - cc = CallControl() - cc.portal_runner_ptr = portal_runner_obj + cc = CallControl(jitdrivers_sd=[FakeJitDriverSD()]) cc.candidate_graphs = [g, g1] op = SpaceOperation('direct_call', [Constant(portal_runner_obj)], Modified: pypy/branch/multijit-3/pypy/jit/codewriter/test/test_codewriter.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/test/test_codewriter.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/test/test_codewriter.py Fri Jun 11 11:52:42 2010 @@ -35,6 +35,12 @@ def look_inside_graph(self, graph): return graph.name != 'dont_look' +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + self.virtualizable_info = None + def test_loop(): def f(a, b): @@ -70,11 +76,11 @@ def fff(a, b): return ggg(b) - ggg(a) rtyper = support.annotate(fff, [35, 42]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) - jitcode = cw.mainjitcode + jitcode = jitdriver_sd.mainjitcode print jitcode.dump() [jitcode2] = cw.assembler.descrs print jitcode2.dump() @@ -117,7 +123,7 @@ return x().id + y().id + dont_look(n) rtyper = support.annotate(f, [35]) maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # @@ -144,10 +150,10 @@ def f(n): return abs(n) rtyper = support.annotate(f, [35]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # - s = cw.mainjitcode.dump() + s = jitdriver_sd.mainjitcode.dump() assert "inline_call_ir_i " in s Modified: pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py Fri Jun 11 11:52:42 2010 @@ -68,11 +68,8 @@ return FakeDescr() def calldescr_canraise(self, calldescr): return calldescr is not self._descr_cannot_raise - def found_jitdriver(self, jitdriver): - assert isinstance(jitdriver, JitDriver) - self.jitdriver = jitdriver - def getjitdriver(self): - return self.jitdriver + def get_vinfo(self, VTYPEPTR): + return None class FakeCallControlWithVRefInfo: class virtualref_info: From arigo at codespeak.net Fri Jun 11 12:52:15 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 12:52:15 +0200 (CEST) Subject: [pypy-svn] r75262 - in pypy/branch/multijit-3/pypy/jit: codewriter codewriter/test metainterp metainterp/test Message-ID: <20100611105215.50DA9282B90@codespeak.net> Author: arigo Date: Fri Jun 11 12:52:13 2010 New Revision: 75262 Added: pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py (contents, props changed) Modified: pypy/branch/multijit-3/pypy/jit/codewriter/call.py pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py pypy/branch/multijit-3/pypy/jit/codewriter/jitcode.py pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py Log: Start porting metainterp/pyjitpl. Modified: pypy/branch/multijit-3/pypy/jit/codewriter/call.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/call.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/call.py Fri Jun 11 12:52:13 2010 @@ -147,6 +147,7 @@ def grab_initial_jitcodes(self): for jd in self.jitdrivers_sd: jd.mainjitcode = self.get_jitcode(jd.portal_graph) + jd.mainjitcode.is_portal = True def enum_pending_graphs(self): while self.unfinished_graphs: Modified: pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/codewriter.py Fri Jun 11 12:52:13 2010 @@ -37,7 +37,7 @@ # # step 1: mangle the graph so that it contains the final instructions # that we want in the JitCode, but still as a control flow graph - transform_graph(graph, self.cpu, self.callcontrol) + transform_graph(graph, self.cpu, self.callcontrol, portal_jd) # # step 2: perform register allocation on it regallocs = {} Modified: pypy/branch/multijit-3/pypy/jit/codewriter/jitcode.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/jitcode.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/jitcode.py Fri Jun 11 12:52:13 2010 @@ -13,6 +13,7 @@ self.name = name self.fnaddr = fnaddr self.calldescr = calldescr + self.is_portal = False self._called_from = called_from # debugging self._ssarepr = None # debugging @@ -24,11 +25,11 @@ self.constants_i = constants_i or self._empty_i self.constants_r = constants_r or self._empty_r self.constants_f = constants_f or self._empty_f - # encode the three num_regs into a single integer + # encode the three num_regs into a single char each assert num_regs_i < 256 and num_regs_r < 256 and num_regs_f < 256 - self.num_regs_encoded = ((num_regs_i << 16) | - (num_regs_f << 8) | - (num_regs_r << 0)) + self.c_num_regs_i = chr(num_regs_i) + self.c_num_regs_r = chr(num_regs_r) + self.c_num_regs_f = chr(num_regs_f) self.liveness = make_liveness_cache(liveness) self._startpoints = startpoints # debugging self._alllabels = alllabels # debugging @@ -37,13 +38,13 @@ return heaptracker.adr2int(self.fnaddr) def num_regs_i(self): - return self.num_regs_encoded >> 16 - - def num_regs_f(self): - return (self.num_regs_encoded >> 8) & 0xFF + return ord(self.c_num_regs_i) def num_regs_r(self): - return self.num_regs_encoded & 0xFF + return ord(self.c_num_regs_r) + + def num_regs_f(self): + return ord(self.c_num_regs_f) def has_liveness_info(self, pc): return pc in self.liveness Modified: pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/jtransform.py Fri Jun 11 12:52:13 2010 @@ -13,19 +13,20 @@ from pypy.translator.simplify import get_funcobj -def transform_graph(graph, cpu=None, callcontrol=None): +def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None): """Transform a control flow graph to make it suitable for being flattened in a JitCode. """ - t = Transformer(cpu, callcontrol) + t = Transformer(cpu, callcontrol, portal_jd) t.transform(graph) class Transformer(object): - def __init__(self, cpu=None, callcontrol=None): + def __init__(self, cpu=None, callcontrol=None, portal_jd=None): self.cpu = cpu self.callcontrol = callcontrol + self.portal_jd = portal_jd # non-None only for the portal graph(s) def transform(self, graph): self.graph = graph @@ -773,9 +774,14 @@ return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver) def handle_jit_marker__jit_merge_point(self, op, jitdriver): + assert self.portal_jd is not None, ( + "'jit_merge_point' in non-portal graph!") + assert jitdriver is self.portal_jd.jitdriver, ( + "general mix-up of jitdrivers?") ops = self.promote_greens(op.args[2:], jitdriver) num_green_args = len(jitdriver.greens) - args = (self.make_three_lists(op.args[2:2+num_green_args]) + + args = ([Constant(self.portal_jd.index, lltype.Signed)] + + self.make_three_lists(op.args[2:2+num_green_args]) + self.make_three_lists(op.args[2+num_green_args:])) op1 = SpaceOperation('jit_merge_point', args, None) return ops + [op1] Modified: pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/multijit-3/pypy/jit/codewriter/test/test_flatten.py Fri Jun 11 12:52:13 2010 @@ -115,13 +115,13 @@ return self.rtyper.annotator.translator.graphs def encoding_test(self, func, args, expected, - transform=False, liveness=False, cc=None): + transform=False, liveness=False, cc=None, jd=None): graphs = self.make_graphs(func, args) #graphs[0].show() if transform: from pypy.jit.codewriter.jtransform import transform_graph cc = cc or FakeCallControl() - transform_graph(graphs[0], FakeCPU(self.rtyper), cc) + transform_graph(graphs[0], FakeCPU(self.rtyper), cc, jd) ssarepr = flatten_graph(graphs[0], fake_regallocs(), _include_all_exc_links=not transform) if liveness: @@ -581,13 +581,16 @@ def f(x, y): myjitdriver.jit_merge_point(x=x, y=y) myjitdriver.can_enter_jit(x=y, y=x) + class FakeJitDriverSD: + jitdriver = myjitdriver + index = 27 self.encoding_test(f, [4, 5], """ -live- %i0, %i1 int_guard_value %i0 - jit_merge_point I[%i0], R[], F[], I[%i1], R[], F[] + jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[] can_enter_jit void_return - """, transform=True, liveness=True) + """, transform=True, liveness=True, jd=FakeJitDriverSD()) def test_keepalive(self): S = lltype.GcStruct('S') Modified: pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py Fri Jun 11 12:52:13 2010 @@ -775,8 +775,8 @@ def bhimpl_can_enter_jit(): pass - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_jit_merge_point(self, *args): + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_jit_merge_point(self, jdindex, *args): if self.nextblackholeinterp is None: # we are the last level CRN = self.builder.metainterp_sd.ContinueRunningNormally raise CRN(*args) @@ -791,54 +791,55 @@ # result. sd = self.builder.metainterp_sd if sd.result_type == 'void': - self.bhimpl_recursive_call_v(*args) + self.bhimpl_recursive_call_v(jdindex, *args) self.bhimpl_void_return() elif sd.result_type == 'int': - x = self.bhimpl_recursive_call_i(*args) + x = self.bhimpl_recursive_call_i(jdindex, *args) self.bhimpl_int_return(x) elif sd.result_type == 'ref': - x = self.bhimpl_recursive_call_r(*args) + x = self.bhimpl_recursive_call_r(jdindex, *args) self.bhimpl_ref_return(x) elif sd.result_type == 'float': - x = self.bhimpl_recursive_call_f(*args) + x = self.bhimpl_recursive_call_f(jdindex, *args) self.bhimpl_float_return(x) assert False - def get_portal_runner(self): + def get_portal_runner(self, jdindex): metainterp_sd = self.builder.metainterp_sd - fnptr = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + jitdriver_sd = metainterp_sd.jitdrivers_sd[jdindex] + fnptr = llmemory.cast_ptr_to_adr(jitdriver_sd.portal_runner_ptr) fnptr = heaptracker.adr2int(fnptr) - calldescr = metainterp_sd.portal_code.calldescr + calldescr = jitdriver_sd.mainjitcode.calldescr return fnptr, calldescr - @arguments("self", "I", "R", "F", "I", "R", "F", returns="i") - def bhimpl_recursive_call_i(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="i") + def bhimpl_recursive_call_i(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_i(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="r") - def bhimpl_recursive_call_r(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="r") + def bhimpl_recursive_call_r(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_r(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="f") - def bhimpl_recursive_call_f(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="f") + def bhimpl_recursive_call_f(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_f(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_recursive_call_v(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_recursive_call_v(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_v(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, Added: pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py ============================================================================== --- (empty file) +++ pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py Fri Jun 11 12:52:13 2010 @@ -0,0 +1,17 @@ + + +class JitDriverStaticData: + """There is one instance of this class per JitDriver used in the program. + """ + # This is just a container with the following attributes (... set by): + # self.jitdriver ... pypy.jit.metainterp.warmspot + # self.portal_graph ... pypy.jit.metainterp.warmspot + # self.portal_runner_ptr ... pypy.jit.metainterp.warmspot + # self.num_green_args ... pypy.jit.metainterp.warmspot + # self.result_type ... pypy.jit.metainterp.warmspot + # self.virtualizable_info... pypy.jit.metainterp.warmspot + # self.index ... pypy.jit.codewriter.call + # self.mainjitcode ... pypy.jit.codewriter.call + + def _freeze_(self): + return True Modified: pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 12:52:13 2010 @@ -56,6 +56,7 @@ self.parent_resumedata_snapshot = None self.parent_resumedata_frame_info_list = None + @specialize.arg(3) def copy_constants(self, registers, constants, ConstClass): """Copy jitcode.constants[0] to registers[255], jitcode.constants[1] to registers[254], @@ -68,7 +69,6 @@ assert j >= 0 registers[j] = ConstClass(constants[i]) i -= 1 - copy_constants._annspecialcase_ = 'specialize:arg(3)' def cleanup_registers(self): # To avoid keeping references alive, this cleans up the registers_r. @@ -80,6 +80,7 @@ # ------------------------------ # Decoding of the JitCode + @specialize.arg(4) def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): assert argcode in 'IRF' code = self.bytecode @@ -92,7 +93,6 @@ elif argcode == 'F': reg = self.registers_f[index] else: raise AssertionError(argcode) outvalue[startindex+i] = reg - prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' def get_current_position_info(self): return self.jitcode.get_live_vars_info(self.pc) @@ -518,15 +518,15 @@ return not isstandard def _get_virtualizable_field_index(self, fielddescr): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.array_field_descrs[index] def _get_virtualizable_array_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.array_descrs[index] @arguments("orgpc", "box", "descr") @@ -557,7 +557,7 @@ def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] @@ -606,7 +606,7 @@ arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, fdescr, box) return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[fdescr] @@ -945,7 +945,7 @@ guard_op = metainterp.history.record(opnum, moreargs, None, descr=resumedescr) virtualizable_boxes = None - if metainterp.staticdata.virtualizable_info is not None: + if metainterp.jitdriver_sd.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes saved_pc = self.pc if resumepc >= 0: @@ -1140,22 +1140,16 @@ self.setup_indirectcalltargets(asm.indirectcalltargets) self.setup_list_of_addr2name(asm.list_of_addr2name) # - self.portal_code = codewriter.mainjitcode - self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.jitdrivers_sd = codewriter.callcontrol.jitdrivers_sd self.virtualref_info = codewriter.callcontrol.virtualref_info - self.virtualizable_info = codewriter.callcontrol.virtualizable_info - RESULT = codewriter.portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: + XXX self.num_green_args = warmrunnerdesc.num_green_args self.state = warmrunnerdesc.state if optimizer is not None: self.state.set_param_optimizer(optimizer) - else: - self.num_green_args = 0 - self.state = None self.globaldata = MetaInterpGlobalData(self) def _setup_once(self): @@ -1176,8 +1170,7 @@ # Build the dictionary at run-time. This is needed # because the keys are function/class addresses, so they # can change from run to run. - k = llmemory.cast_ptr_to_adr(self._portal_runner_ptr) - d = {k: 'recursive call'} + d = {} keys = self._addr2name_keys values = self._addr2name_values for i in range(len(keys)): @@ -1236,7 +1229,7 @@ self.resume_virtuals = {} self.resume_virtuals_not_translated = [] # - state = staticdata.state + state = None # XXX staticdata.state if state is not None: self.jit_cell_at_key = state.jit_cell_at_key else: @@ -1269,13 +1262,12 @@ def perform_call(self, jitcode, boxes, greenkey=None): # causes the metainterp to enter the given subfunction - # with a special case for recursive portal calls f = self.newframe(jitcode, greenkey) f.setup_call(boxes) raise ChangeFrame def newframe(self, jitcode, greenkey=None): - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: self.in_recursion += 1 if greenkey is not None: self.portal_trace_positions.append( @@ -1290,7 +1282,7 @@ def popframe(self): frame = self.framestack.pop() - if frame.jitcode is self.staticdata.portal_code: + if frame.jitcode.is_portal: self.in_recursion -= 1 if frame.greenkey is not None: self.portal_trace_positions.append( @@ -1314,14 +1306,15 @@ except SwitchToBlackhole, stb: self.aborted_tracing(stb.reason) sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert resultbox is None raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': + elif result_type == history.INT: raise sd.DoneWithThisFrameInt(resultbox.getint()) - elif sd.result_type == 'ref': + elif result_type == history.REF: raise sd.DoneWithThisFrameRef(self.cpu, resultbox.getref_base()) - elif sd.result_type == 'float': + elif result_type == history.FLOAT: raise sd.DoneWithThisFrameFloat(resultbox.getfloat()) else: assert False @@ -1508,21 +1501,24 @@ self.staticdata.log(sys.exc_info()[0].__name__) raise - def compile_and_run_once(self, *args): + @specialize.arg(1) + def compile_and_run_once(self, jitdriver_sd, *args): debug_start('jit-tracing') self.staticdata._setup_once() self.staticdata.profiler.start_tracing() self.create_empty_history() try: - return self._compile_and_run_once(*args) + original_boxes = self.initialize_original_boxes(jitdriver_sd,*args) + self.jitdriver_sd = jitdriver_sd + return self._compile_and_run_once(original_boxes) finally: self.staticdata.profiler.end_tracing() debug_stop('jit-tracing') - def _compile_and_run_once(self, *args): - original_boxes = self.initialize_state_from_start(*args) + def _compile_and_run_once(self, original_boxes): + self.initialize_state_from_start(original_boxes) self.current_merge_points = [(original_boxes, 0)] - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args original_greenkey = original_boxes[:num_green_args] redkey = original_boxes[num_green_args:] self.resumekey = compile.ResumeFromInterpDescr(original_greenkey, @@ -1589,7 +1585,7 @@ self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) live_arg_boxes = greenboxes + redboxes - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, @@ -1710,17 +1706,18 @@ self.gen_store_back_in_virtualizable() # temporarily put a JUMP to a pseudo-loop sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert exitbox is None exits = [] loop_tokens = sd.loop_tokens_done_with_this_frame_void - elif sd.result_type == 'int': + elif result_type == history.INT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_int - elif sd.result_type == 'ref': + elif result_type == history.REF: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_ref - elif sd.result_type == 'float': + elif result_type == history.FLOAT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_float else: @@ -1752,26 +1749,35 @@ specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args - def _initialize_from_start(self, original_boxes, num_green_args, *args): + @specialize.arg(1) + def initialize_original_boxes(self, jitdriver_sd, *args): + # NB. we pass explicity 'jitdriver_sd' around here, even though it + # might also available as 'self.jitdriver_sd', because we need to + # specialize these functions for the particular *args. + original_boxes = [] + self._fill_original_boxes(jitdriver_sd, original_boxes, + jitdriver_sd.num_green_args, *args) + return original_boxes + + @specialize.arg(1) + def _fill_original_boxes(self, jitdriver_sd, original_boxes, + num_green_args, *args): if args: from pypy.jit.metainterp.warmstate import wrap box = wrap(self.cpu, args[0], num_green_args > 0) original_boxes.append(box) - self._initialize_from_start(original_boxes, num_green_args-1, - *args[1:]) + self._fill_original_boxes(jitdriver_sd, original_boxes, + num_green_args-1, *args[1:]) - def initialize_state_from_start(self, *args): - self.in_recursion = -1 # always one portal around - num_green_args = self.staticdata.num_green_args - original_boxes = [] - self._initialize_from_start(original_boxes, num_green_args, *args) + def initialize_state_from_start(self, original_boxes): # ----- make a new frame ----- + self.in_recursion = -1 # always one portal around self.framestack = [] - f = self.newframe(self.staticdata.portal_code) + f = self.newframe(self.jitdriver_sd.mainjitcode) f.setup_call(original_boxes) + assert self.in_recursion == 0 self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) - return original_boxes def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack @@ -1781,7 +1787,7 @@ self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = original_boxes[vinfo.index_of_virtualizable] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1794,7 +1800,7 @@ self.initialize_virtualizable_enter() def initialize_virtualizable_enter(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.clear_vable_token(virtualizable) @@ -1808,7 +1814,7 @@ # the FORCE_TOKEN is already set at runtime in each vref when # it is created, by optimizeopt.py. # - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1834,7 +1840,7 @@ self.stop_tracking_virtualref(i) def vable_after_residual_call(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1885,7 +1891,7 @@ assert self.last_exc_value_box is None def rebuild_state_after_failure(self, resumedescr): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info self.framestack = [] boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists @@ -1921,13 +1927,13 @@ def check_synchronized_virtualizable(self): if not we_are_translated(): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.check_boxes(virtualizable, self.virtualizable_boxes) def synchronize_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.write_boxes(virtualizable, self.virtualizable_boxes) @@ -1936,7 +1942,7 @@ # Force a reload of the virtualizable fields into the local # boxes (called only in escaping cases). Only call this function # just before SwitchToBlackhole. - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1945,7 +1951,7 @@ self.virtualizable_boxes.append(virtualizable_box) def gen_store_back_in_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: # xxx only write back the fields really modified vbox = self.virtualizable_boxes[-1] @@ -1967,7 +1973,7 @@ assert i + 1 == len(self.virtualizable_boxes) def gen_load_from_other_virtualizable(self, vbox): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info boxes = [] assert vinfo is not None for i in range(vinfo.num_static_extra_boxes): @@ -1991,7 +1997,7 @@ for i in range(len(boxes)): if boxes[i] is oldbox: boxes[i] = newbox - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: boxes = self.virtualizable_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2047,8 +2053,9 @@ assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args args = op.args[num_green_args + 1:] - if self.staticdata.virtualizable_info is not None: - vindex = self.staticdata.virtualizable_info.index_of_virtualizable + vinfo = self.jitdriver_sd.virtualizable_info + if vinfo is not None: + vindex = vinfo.index_of_virtualizable vbox = args[vindex - num_green_args] args = args + self.gen_load_from_other_virtualizable(vbox) # ^^^ and not "+=", which makes 'args' a resizable list Modified: pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 12:52:13 2010 @@ -30,9 +30,17 @@ func._jit_unroll_safe_ = True rtyper = support.annotate(func, values, type_system=type_system) graphs = rtyper.annotator.translator.graphs + result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0] + + class FakeJitDriverSD: + num_green_args = 0 + portal_graph = graphs[0] + virtualizable_info = None + result_type = result_kind + stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - cw = codewriter.CodeWriter(cpu, graphs[0]) + cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()]) testself.cw = cw cw.find_all_graphs(JitPolicy()) # @@ -62,7 +70,8 @@ count_f += 1 else: raise TypeError(T) - blackholeinterp.setposition(cw.mainjitcode, 0) + [jitdriver_sd] = cw.callcontrol.jitdrivers_sd + blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0) blackholeinterp.run() return blackholeinterp._final_result_anytype() @@ -86,8 +95,9 @@ metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame testself.metainterp = metainterp + [jitdriver_sd] = cw.callcontrol.jitdrivers_sd try: - metainterp.compile_and_run_once(*args) + metainterp.compile_and_run_once(jitdriver_sd, *args) except DoneWithThisFrame, e: #if conftest.option.view: # metainterp.stats.view() From arigo at codespeak.net Fri Jun 11 12:58:16 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 12:58:16 +0200 (CEST) Subject: [pypy-svn] r75263 - in pypy/branch/multijit-3/pypy/jit/metainterp: . test Message-ID: <20100611105816.12087282B90@codespeak.net> Author: arigo Date: Fri Jun 11 12:58:14 2010 New Revision: 75263 Modified: pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py Log: Fixes. With this, most interp_operations() tests run again. Modified: pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 12:58:14 2010 @@ -659,6 +659,7 @@ def _opimpl_recursive_call(self, greenboxes, redboxes): allboxes = greenboxes + redboxes metainterp_sd = self.metainterp.staticdata + xxxx portal_code = metainterp_sd.portal_code warmrunnerstate = metainterp_sd.state token = None @@ -1344,14 +1345,17 @@ in_recursion = -1 for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + assert jitcode.is_portal == len([ + jd for jd in self.staticdata.jitdrivers_sd + if jd.mainjitcode is jitcode]) + if jitcode.is_portal: in_recursion += 1 if in_recursion != self.in_recursion: print "in_recursion problem!!!" print in_recursion, self.in_recursion for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: print "P", else: print " ", Modified: pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 12:58:14 2010 @@ -37,6 +37,7 @@ portal_graph = graphs[0] virtualizable_info = None result_type = result_kind + portal_runner_ptr = "???" stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) From antocuni at codespeak.net Fri Jun 11 13:27:47 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 13:27:47 +0200 (CEST) Subject: [pypy-svn] r75264 - in pypy/branch/sys-prefix: lib-python lib/pypy1.2/lib-python pypy pypy/annotation/test pypy/bin pypy/config pypy/doc/config pypy/interpreter pypy/jit/backend pypy/jit/backend/x86 pypy/jit/backend/x86/tool pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/module/__builtin__/test pypy/module/_codecs/test pypy/module/_sre/test pypy/module/sys pypy/module/sys/test pypy/module/test_lib_pypy pypy/rlib/parsing/test pypy/rlib/rsdl/test pypy/rpython/microbench pypy/tool pypy/tool/algo/test pypy/tool/pytest pypy/tool/test pypy/translator pypy/translator/benchmark pypy/translator/c pypy/translator/c/gcc pypy/translator/c/test pypy/translator/cli/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/microbench/pybench pypy/translator/sandbox pypy/translator/sandbox/test pypy/translator/test pypy/translator/tool Message-ID: <20100611112747.A67B9282BD6@codespeak.net> Author: antocuni Date: Fri Jun 11 13:27:44 2010 New Revision: 75264 Added: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/ - copied from r75257, pypy/branch/sys-prefix/lib-python/ Removed: pypy/branch/sys-prefix/lib-python/ Modified: pypy/branch/sys-prefix/pypy/annotation/test/autopath.py pypy/branch/sys-prefix/pypy/bin/autopath.py pypy/branch/sys-prefix/pypy/config/autopath.py pypy/branch/sys-prefix/pypy/conftest.py pypy/branch/sys-prefix/pypy/doc/config/autopath.py pypy/branch/sys-prefix/pypy/interpreter/baseobjspace.py pypy/branch/sys-prefix/pypy/jit/backend/autopath.py pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py pypy/branch/sys-prefix/pypy/jit/tl/autopath.py pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py pypy/branch/sys-prefix/pypy/jit/tool/autopath.py pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py pypy/branch/sys-prefix/pypy/module/sys/state.py pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py pypy/branch/sys-prefix/pypy/module/test_lib_pypy/test_array.py pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py pypy/branch/sys-prefix/pypy/tool/autopath.py pypy/branch/sys-prefix/pypy/tool/lib_pypy.py pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py pypy/branch/sys-prefix/pypy/tool/pytest/confpath.py pypy/branch/sys-prefix/pypy/tool/stdlib___future__.py pypy/branch/sys-prefix/pypy/tool/stdlib_opcode.py pypy/branch/sys-prefix/pypy/tool/test/autopath.py pypy/branch/sys-prefix/pypy/tool/test/test_lib_pypy.py pypy/branch/sys-prefix/pypy/translator/autopath.py pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py pypy/branch/sys-prefix/pypy/translator/c/autopath.py pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py pypy/branch/sys-prefix/pypy/translator/geninterplevel.py pypy/branch/sys-prefix/pypy/translator/goal/autopath.py pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py pypy/branch/sys-prefix/pypy/translator/test/autopath.py pypy/branch/sys-prefix/pypy/translator/tool/autopath.py Log: move lib-python to lib/pypy1.2 Modified: pypy/branch/sys-prefix/pypy/annotation/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/annotation/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/annotation/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/bin/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/bin/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/bin/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/config/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/config/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/config/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/conftest.py ============================================================================== --- pypy/branch/sys-prefix/pypy/conftest.py (original) +++ pypy/branch/sys-prefix/pypy/conftest.py Fri Jun 11 13:27:44 2010 @@ -10,7 +10,7 @@ # pytest settings pytest_plugins = "resultlog", -rsyncdirs = ['.', '../lib-python', '../demo'] +rsyncdirs = ['.', '../lib', '../demo'] rsyncignore = ['_cache'] collect_ignore = ['./lib/py'] Modified: pypy/branch/sys-prefix/pypy/doc/config/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/config/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/doc/config/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/sys-prefix/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/sys-prefix/pypy/interpreter/baseobjspace.py Fri Jun 11 13:27:44 2010 @@ -385,7 +385,7 @@ def get_builtinmodule_to_install(self): """NOT_RPYTHON""" - from pypy.tool.lib_pypy import get_lib_pypy_dir + from pypy.tool.lib_pypy import LIB_PYPY try: return self._builtinmodule_list except AttributeError: @@ -403,10 +403,9 @@ if ('time2' in modules or 'rctime' in modules) and 'time' in modules: modules.remove('time') - lib_pypy = get_lib_pypy_dir() if not self.config.objspace.nofaking: for modname in self.ALL_BUILTIN_MODULES: - if not lib_pypy.join(modname+'.py').check(file=True): + if not LIB_PYPY.join(modname+'.py').check(file=True): modules.append('faked+'+modname) self._builtinmodule_list = modules Modified: pypy/branch/sys-prefix/pypy/jit/backend/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tl/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tl/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tl/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tool/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/state.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/state.py Fri Jun 11 13:27:44 2010 @@ -36,19 +36,19 @@ # build the initial path from the srcdir, which is the path of # the "dist" directory of a PyPy checkout. from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION + libdir = os.path.join(srcdir, 'lib') + pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], CPYTHON_VERSION[1], CPYTHON_VERSION[2]) - lib_python = os.path.join(srcdir, 'lib-python') + lib_python = os.path.join(pypyxy_dir, 'lib-python') python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) checkdir(python_std_lib_modified) - libdir = os.path.join(srcdir, 'lib') - pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) lib_pypy = os.path.join(pypyxy_dir, 'lib_pypy') checkdir(lib_pypy) Modified: pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/test_lib_pypy/test_array.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/test_lib_pypy/test_array.py (original) +++ pypy/branch/sys-prefix/pypy/module/test_lib_pypy/test_array.py Fri Jun 11 13:27:44 2010 @@ -73,11 +73,11 @@ class TestArrayOnTopOfCPython(BaseArrayTests): def setup_class(cls): - from pypy.tool.lib_pypy import get_lib_pypy_dir + from pypy.tool.lib_pypy import LIB_PYPY if not hasattr(struct, 'pack_into'): py.test.skip("requires CPython >= 2.5") import new - path = get_lib_pypy_dir().join('array.py') + path = LIB_PYPY.join('array.py') myarraymodule = new.module('array') execfile(str(path), myarraymodule.__dict__) cls.array = myarraymodule Modified: pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/lib_pypy.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/lib_pypy.py (original) +++ pypy/branch/sys-prefix/pypy/tool/lib_pypy.py Fri Jun 11 13:27:44 2010 @@ -1,13 +1,19 @@ import py import pypy -from pypy.module.sys.version import PYPY_VERSION +import pypy.module +from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION -def get_lib_pypy_dir(): - prefix = py.path.local(pypy.__path__[0]).dirpath() - pypy_ver = 'pypy%d.%d' % PYPY_VERSION[:2] - return prefix.join('lib', pypy_ver, 'lib_pypy') +prefix = py.path.local(pypy.__path__[0]).dirpath() +pypy_ver = 'pypy%d.%d' % PYPY_VERSION[:2] + +LIB_PYPY = prefix.join('lib', pypy_ver, 'lib_pypy') +LIB_PYTHON = prefix.join('lib', pypy_ver, 'lib-python') +LIB_PYTHON_VANILLA = LIB_PYTHON.join('%d.%d.%d' % CPYTHON_VERSION[:3]) +LIB_PYTHON_MODIFIED = LIB_PYTHON.join('modified-%d.%d.%d' % CPYTHON_VERSION[:3]) + +del prefix +del pypy_ver def import_from_lib_pypy(modname): - dirname = get_lib_pypy_dir() - modname = dirname.join(modname+'.py') + modname = LIB_PYPY.join(modname+'.py') return modname.pyimport() Modified: pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/pytest/confpath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/pytest/confpath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/pytest/confpath.py Fri Jun 11 13:27:44 2010 @@ -1,11 +1,12 @@ import autopath import py import pypy +from pypy.tool import lib_pypy pypydir = py.path.local(pypy.__file__).dirpath() distdir = pypydir.dirpath() testresultdir = distdir.join('testresult') assert pypydir.check(dir=1) -libpythondir = distdir.join('lib-python') -regrtestdir = libpythondir.join('2.5.2', 'test') -modregrtestdir = libpythondir.join('modified-2.5.2', 'test') +libpythondir = lib_pypy.LIB_PYTHON +regrtestdir = lib_pypy.LIB_PYTHON_VANILLA.join('test') +modregrtestdir = lib_pypy.LIB_PYTHON_MODIFIED.join('test') Modified: pypy/branch/sys-prefix/pypy/tool/stdlib___future__.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/stdlib___future__.py (original) +++ pypy/branch/sys-prefix/pypy/tool/stdlib___future__.py Fri Jun 11 13:27:44 2010 @@ -1,8 +1,8 @@ # load __future__.py constants def load_module(): - import py - module_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/2.5.2/__future__.py') + from pypy.tool.lib_pypy import LIB_PYTHON_VANILLA + module_path = LIB_PYTHON_VANILLA.join('__future__.py') execfile(str(module_path), globals()) load_module() Modified: pypy/branch/sys-prefix/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/stdlib_opcode.py (original) +++ pypy/branch/sys-prefix/pypy/tool/stdlib_opcode.py Fri Jun 11 13:27:44 2010 @@ -106,8 +106,8 @@ opmap as host_opmap, HAVE_ARGUMENT as host_HAVE_ARGUMENT) def load_pypy_opcode(): - import py - opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.5.2/opcode.py') + from pypy.tool.lib_pypy import LIB_PYTHON_MODIFIED + opcode_path = LIB_PYTHON_MODIFIED.join('opcode.py') d = {} execfile(str(opcode_path), d) for name in __all__: Modified: pypy/branch/sys-prefix/pypy/tool/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/test/test_lib_pypy.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/test/test_lib_pypy.py (original) +++ pypy/branch/sys-prefix/pypy/tool/test/test_lib_pypy.py Fri Jun 11 13:27:44 2010 @@ -2,9 +2,14 @@ from pypy.tool import lib_pypy def test_lib_pypy_exists(): - dirname = lib_pypy.get_lib_pypy_dir() + dirname = lib_pypy.LIB_PYPY assert dirname.check(dir=1) +def test_lib_python_exists(): + assert lib_pypy.LIB_PYTHON.check(dir=1) + assert lib_pypy.LIB_PYTHON_VANILLA.check(dir=1) + assert lib_pypy.LIB_PYTHON_MODIFIED.check(dir=1) + def test_import_from_lib_pypy(): binascii = lib_pypy.import_from_lib_pypy('binascii') assert type(binascii) is type(lib_pypy) Modified: pypy/branch/sys-prefix/pypy/translator/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py Fri Jun 11 13:27:44 2010 @@ -37,8 +37,7 @@ partdir = head head, tail = os.path.split(head) if tail == part: - # check if "../py/__init__.py" exists - checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') if not os.path.exists(checkfile): error = "Cannot find %r" % (os.path.normpath(checkfile),) break @@ -127,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/geninterplevel.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/geninterplevel.py (original) +++ pypy/branch/sys-prefix/pypy/translator/geninterplevel.py Fri Jun 11 13:27:44 2010 @@ -1474,7 +1474,7 @@ dic = initfunc(space) # and now use the members of the dict """ - from pypy.tool.lib_pypy import get_lib_pypy_dir + from pypy.tool.lib_pypy import LIB_PYPY # create something like a module if type(sourcetext) is str: code = py.code.Source(sourcetext).compile() @@ -1486,7 +1486,7 @@ dic['__file__'] = filename # XXX allow the app-level code to contain e.g. "import _formatting" - libdir = str(get_lib_pypy_dir()) + libdir = str(LIB_PYPY) sys.path.insert(0, libdir) try: if faked_set: Modified: pypy/branch/sys-prefix/pypy/translator/goal/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py Fri Jun 11 13:27:44 2010 @@ -469,17 +469,17 @@ # setup code for test_get_library_path # ------------------------------------ from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION - libroot = 'share/pypy-%d.%d' % PYPY_VERSION[:2] + libroot = 'lib/pypy%d.%d' % PYPY_VERSION[:2] cpy_ver = '%d.%d.%d' % CPYTHON_VERSION[:3] goal_dir = os.path.dirname(app_main) # build a directory hierarchy like which contains both bin/pypy-c and - # share/pypy-1.2/* + # lib/pypy1.2/* prefix = udir.join('pathtest') fake_exe = prefix.join('bin/pypy-c').ensure(file=1) - share_pypy = prefix.join(libroot).ensure(dir=1) - expected_path = [str(share_pypy.join(subdir).ensure(dir=1)) - for subdir in ('pypy/lib', + pypyxy = prefix.join(libroot).ensure(dir=1) + expected_path = [str(pypyxy.join(subdir).ensure(dir=1)) + for subdir in ('lib_pypy', 'lib-python/modified-%s' % cpy_ver, 'lib-python/%s' % cpy_ver)] Modified: pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/test/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/tool/autopath.py Fri Jun 11 13:27:44 2010 @@ -126,8 +126,8 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py -libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) +import py # note: py is imported only AFTER the path has been set +libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': From antocuni at codespeak.net Fri Jun 11 13:33:14 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 13:33:14 +0200 (CEST) Subject: [pypy-svn] r75265 - pypy/branch/sys-prefix/pypy/jit/tl Message-ID: <20100611113314.CA5FA282BD6@codespeak.net> Author: antocuni Date: Fri Jun 11 13:33:13 2010 New Revision: 75265 Removed: pypy/branch/sys-prefix/pypy/jit/tl/run_all_tests.py Log: kill out of date file From antocuni at codespeak.net Fri Jun 11 13:52:10 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 13:52:10 +0200 (CEST) Subject: [pypy-svn] r75266 - in pypy/branch/sys-prefix/pypy/tool: . test Message-ID: <20100611115210.B334A282B90@codespeak.net> Author: antocuni Date: Fri Jun 11 13:52:09 2010 New Revision: 75266 Modified: pypy/branch/sys-prefix/pypy/tool/package.py pypy/branch/sys-prefix/pypy/tool/test/test_package.py Log: fix package.py for the new directory layout Modified: pypy/branch/sys-prefix/pypy/tool/package.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/package.py (original) +++ pypy/branch/sys-prefix/pypy/tool/package.py Fri Jun 11 13:52:09 2010 @@ -38,14 +38,10 @@ raise PyPyCNotFound('Please compile pypy first, using translate.py') builddir = udir.ensure("build", dir=True) pypydir = builddir.ensure(name, dir=True) - shutil.copytree(str(basedir.join('lib-python')), - str(pypydir.join('lib-python')), - ignore=ignore_patterns('.svn', '*.pyc', '*~')) - # Careful: to copy pypy/lib, copying just the svn-tracked files + # Careful: to copy lib_pypy, copying just the svn-tracked files # would not be enough: there are also ctypes_config_cache/_*_cache.py. - pypydir.ensure('pypy', dir=True) - shutil.copytree(str(basedir.join('pypy', 'lib')), - str(pypydir.join('pypy', 'lib')), + shutil.copytree(str(basedir.join('lib')), + str(pypydir.join('lib')), ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) Modified: pypy/branch/sys-prefix/pypy/tool/test/test_package.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/test/test_package.py (original) +++ pypy/branch/sys-prefix/pypy/tool/test/test_package.py Fri Jun 11 13:52:09 2010 @@ -2,6 +2,7 @@ import py from pypy.tool.autopath import pypydir from pypy.tool.package import main +from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION import tarfile, os def test_dir_structure(): @@ -14,15 +15,18 @@ fake_pypy_c = False try: builddir = main(py.path.local(pypydir).dirpath(), 'test') - assert builddir.join('test', 'lib-python', '2.5.2', 'test').check() - assert builddir.join('test', 'bin', 'pypy-c').check() - assert builddir.join('test', 'pypy', 'lib', 'syslog.py').check() - assert not builddir.join('test', 'pypy', 'lib', 'py').check() - assert not builddir.join('test', 'pypy', 'lib', 'ctypes_configure').check() - assert builddir.join('test', 'LICENSE').check() - assert builddir.join('test', 'README').check() + prefix = builddir.join('test') + pypyxy = 'pypy%d.%d' % PYPY_VERSION[:2] + cpyver = '%d.%d.%d' % CPYTHON_VERSION[:3] + assert prefix.join('lib', pypyxy, 'lib-python', cpyver, 'test').check() + assert prefix.join('bin', 'pypy-c').check() + assert prefix.join('lib', pypyxy, 'lib_pypy', 'syslog.py').check() + assert not prefix.join('lib', pypyxy, 'lib_pypy', 'py').check() + assert not prefix.join('lib', pypyxy, 'lib_pypy', 'ctypes_configure').check() + assert prefix.join('LICENSE').check() + assert prefix.join('README').check() th = tarfile.open(str(builddir.join('test.tar.bz2'))) - assert th.getmember('test/pypy/lib/syslog.py') + assert th.getmember('test/lib/%s/lib_pypy/syslog.py' % pypyxy) finally: if fake_pypy_c: pypy_c.remove() From afa at codespeak.net Fri Jun 11 15:08:22 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 15:08:22 +0200 (CEST) Subject: [pypy-svn] r75267 - in pypy/trunk/pypy/translator/platform: . test Message-ID: <20100611130822.0399F282BEC@codespeak.net> Author: afa Date: Fri Jun 11 15:08:21 2010 New Revision: 75267 Modified: pypy/trunk/pypy/translator/platform/__init__.py pypy/trunk/pypy/translator/platform/test/test_platform.py Log: on Windows, fix some tests in the platform package Modified: pypy/trunk/pypy/translator/platform/__init__.py ============================================================================== --- pypy/trunk/pypy/translator/platform/__init__.py (original) +++ pypy/trunk/pypy/translator/platform/__init__.py Fri Jun 11 15:08:21 2010 @@ -62,9 +62,20 @@ def execute(self, executable, args=None, env=None, compilation_info=None): if env is None: env = os.environ.copy() - if compilation_info is not None: + else: + env = env.copy() + + # On Windows, %SystemRoot% must be present for most programs to start + if (os.name == 'nt' and + "SystemRoot" not in env and + "SystemRoot" in os.environ): + env["SystemRoot"] = os.environ["SystemRoot"] + + # Set LD_LIBRARY_PATH on posix platforms + if os.name == 'posix' and compilation_info is not None: env['LD_LIBRARY_PATH'] = ':'.join( [str(i) for i in compilation_info.library_dirs]) + returncode, stdout, stderr = _run_subprocess(str(executable), args, env) return ExecutionResult(returncode, stdout, stderr) Modified: pypy/trunk/pypy/translator/platform/test/test_platform.py ============================================================================== --- pypy/trunk/pypy/translator/platform/test/test_platform.py (original) +++ pypy/trunk/pypy/translator/platform/test/test_platform.py Fri Jun 11 15:08:21 2010 @@ -113,7 +113,7 @@ def test_environment_inheritance(self): # make sure that environment is inherited cmd = 'import os; print os.environ["_SOME_VARIABLE_%d"]' - res = self.platform.execute('python', ['-c', cmd % 1], + res = self.platform.execute(sys.executable, ['-c', cmd % 1], env={'_SOME_VARIABLE_1':'xyz'}) assert 'xyz' in res.out os.environ['_SOME_VARIABLE_2'] = 'zyz' From antocuni at codespeak.net Fri Jun 11 15:10:14 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 15:10:14 +0200 (CEST) Subject: [pypy-svn] r75268 - in pypy/branch/sys-prefix/pypy: tool translator/sandbox translator/sandbox/test Message-ID: <20100611131014.E427E282BEC@codespeak.net> Author: antocuni Date: Fri Jun 11 15:10:13 2010 New Revision: 75268 Modified: pypy/branch/sys-prefix/pypy/tool/lib_pypy.py pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py Log: fix pypy_interact to follow the new directory layout Modified: pypy/branch/sys-prefix/pypy/tool/lib_pypy.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/lib_pypy.py (original) +++ pypy/branch/sys-prefix/pypy/tool/lib_pypy.py Fri Jun 11 15:10:13 2010 @@ -6,8 +6,9 @@ prefix = py.path.local(pypy.__path__[0]).dirpath() pypy_ver = 'pypy%d.%d' % PYPY_VERSION[:2] -LIB_PYPY = prefix.join('lib', pypy_ver, 'lib_pypy') -LIB_PYTHON = prefix.join('lib', pypy_ver, 'lib-python') +LIB_ROOT = prefix.join('lib', pypy_ver) +LIB_PYPY = LIB_ROOT.join('lib_pypy') +LIB_PYTHON = LIB_ROOT.join('lib-python') LIB_PYTHON_VANILLA = LIB_PYTHON.join('%d.%d.%d' % CPYTHON_VERSION[:3]) LIB_PYTHON_MODIFIED = LIB_PYTHON.join('modified-%d.%d.%d' % CPYTHON_VERSION[:3]) Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py Fri Jun 11 15:10:13 2010 @@ -26,6 +26,7 @@ from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile +from pypy.tool.lib_pypy import LIB_ROOT class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): debug = True @@ -50,21 +51,15 @@ tmpdirnode = Dir({}) else: tmpdirnode = RealDir(self.tmpdir, exclude=exclude) - pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) + libpath = str(LIB_ROOT.dirpath()) return Dir({ 'bin': Dir({ 'pypy-c': RealFile(self.executable), - 'lib-python': RealDir(os.path.join(pypydist, 'lib-python'), - exclude=exclude), - # XXX: fix this (and write a test!) - 'pypy': Dir({ - 'lib': RealDir(os.path.join(pypydist, 'pypy', 'lib'), - exclude=exclude), + 'lib': RealDir(libpath, exclude=exclude), }), - }), - 'tmp': tmpdirnode, - }) + 'tmp': tmpdirnode, + }) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py Fri Jun 11 15:10:13 2010 @@ -24,7 +24,7 @@ assert_(argv[0] == '/bin/pypy-c', "bad argv[0]") st = os.lstat('/bin/pypy-c') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for /bin/pypy-c") - for dirname in ['/bin/lib-python/2.5.2', '/bin/pypy/lib']: + for dirname in ['/bin/lib/pypy1.2/lib-python/2.5.2', '/bin/lib/pypy1.2/lib_pypy']: st = os.stat(dirname) assert_(stat.S_ISDIR(st.st_mode), "bad st_mode for " + dirname) assert_(os.environ.get('PYTHONPATH') is None, "unexpected $PYTHONPATH") @@ -34,15 +34,15 @@ pass else: assert_(False, "os.stat('site') should have failed") - st = os.stat('/bin/lib-python/modified-2.5.2/site.py') + st = os.stat('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.py') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for .../site.py") try: - os.stat('/bin/lib-python/modified-2.5.2/site.pyc') + os.stat('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.pyc') except OSError: pass else: assert_(False, "os.stat('....pyc') should have failed") - fd = os.open('/bin/lib-python/modified-2.5.2/site.py', os.O_RDONLY, 0666) + fd = os.open('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.py', os.O_RDONLY, 0666) length = 8192 ofs = 0 while True: From afa at codespeak.net Fri Jun 11 15:22:38 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 15:22:38 +0200 (CEST) Subject: [pypy-svn] r75269 - in pypy/trunk/pypy/translator: platform tool tool/test Message-ID: <20100611132238.DA8A5282BEC@codespeak.net> Author: afa Date: Fri Jun 11 15:22:37 2010 New Revision: 75269 Modified: pypy/trunk/pypy/translator/platform/__init__.py pypy/trunk/pypy/translator/platform/darwin.py pypy/trunk/pypy/translator/platform/posix.py pypy/trunk/pypy/translator/platform/windows.py pypy/trunk/pypy/translator/tool/cbuild.py pypy/trunk/pypy/translator/tool/test/test_cbuild.py Log: Move the generation of the "-exported_symbols_list" to the platform package, and merge it with the Windows "/EXPORT:xxx" feature on Windows, this gives shorter command lines, and also fix the generation of the Makefile. Modified: pypy/trunk/pypy/translator/platform/__init__.py ============================================================================== --- pypy/trunk/pypy/translator/platform/__init__.py (original) +++ pypy/trunk/pypy/translator/platform/__init__.py Fri Jun 11 15:22:37 2010 @@ -5,6 +5,7 @@ import sys, py, os +from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_log log = py.log.Producer("platform") py.log.setconsumer("platform", ansi_log) @@ -123,6 +124,18 @@ for line in stderr.splitlines(): log.WARNING(line) + def _make_response_file(self, prefix): + """Creates a temporary file with the specified prefix, + and returns its name""" + # Build unique filename + num = 0 + while 1: + response_file = udir.join('%s%i' % (prefix, num)) + num += 1 + if not response_file.check(): + break + return response_file + def _preprocess_include_dirs(self, include_dirs): return include_dirs @@ -144,9 +157,15 @@ library_dirs = self._libdirs(library_dirs) libraries = self._libs(eci.libraries) link_files = self._linkfiles(eci.link_files) - return (library_dirs + self.link_flags + + export_flags = self._exportsymbols_link_flags(eci) + return (library_dirs + self.link_flags + export_flags + link_files + list(eci.link_extra) + libraries) + def _exportsymbols_link_flags(self, eci): + if eci.export_symbols: + raise ValueError("This platform does not support export symbols") + return [] + def _finish_linking(self, ofiles, eci, outputfilename, standalone): if outputfilename is None: outputfilename = ofiles[0].purebasename Modified: pypy/trunk/pypy/translator/platform/darwin.py ============================================================================== --- pypy/trunk/pypy/translator/platform/darwin.py (original) +++ pypy/trunk/pypy/translator/platform/darwin.py Fri Jun 11 15:22:37 2010 @@ -56,6 +56,17 @@ include_dirs = self._includedirs(eci.include_dirs) return (args + frameworks + include_dirs) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("_%s\n" % (sym,)) + f.close() + return ["-Wl,-exported_symbols_list,%s" % (response_file,)] + class Darwin_i386(Darwin): name = "darwin_i386" link_flags = ['-arch', 'i386', '-mmacosx-version-min=10.4'] Modified: pypy/trunk/pypy/translator/platform/posix.py ============================================================================== --- pypy/trunk/pypy/translator/platform/posix.py (original) +++ pypy/trunk/pypy/translator/platform/posix.py Fri Jun 11 15:22:37 2010 @@ -37,9 +37,21 @@ return oname def _link_args_from_eci(self, eci, standalone): - eci = eci.convert_exportsymbols_to_file() return Platform._link_args_from_eci(self, eci, standalone) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + f.write("{\n") + for sym in eci.export_symbols: + f.write("%s;\n" % (sym,)) + f.write("};") + f.close() + return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] + def _link(self, cc, ofiles, link_args, standalone, exe_name): args = [str(ofile) for ofile in ofiles] + link_args args += ['-o', str(exe_name)] @@ -61,7 +73,6 @@ def gen_makefile(self, cfiles, eci, exe_name=None, path=None, shared=False): - eci = eci.convert_exportsymbols_to_file() cfiles = [py.path.local(f) for f in cfiles] cfiles += [py.path.local(f) for f in eci.separate_module_files] @@ -77,6 +88,8 @@ if shared: linkflags = self._args_for_shared(linkflags) + linkflags += self._exportsymbols_link_flags(eci) + if shared: libname = exe_name.new(ext='').basename target_name = 'lib' + exe_name.new(ext=self.so_ext).basename Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Fri Jun 11 15:22:37 2010 @@ -139,8 +139,18 @@ def _link_args_from_eci(self, eci, standalone): # Windows needs to resolve all symbols even for DLLs - args = super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) - return args + ['/EXPORT:%s' % symbol for symbol in eci.export_symbols] + return super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) + + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("exported_symbols_") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("/EXPORT:%s\n" % (sym,)) + f.close() + return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): oname = cfile.new(ext='obj') @@ -179,7 +189,7 @@ # Microsoft compilers write compilation errors to stdout stderr = stdout + stderr errorfile = outname.new(ext='errors') - errorfile.write(stderr) + errorfile.write(stderr, mode='wb') stderrlines = stderr.splitlines() for line in stderrlines: log.ERROR(line) @@ -207,6 +217,7 @@ if shared: linkflags = self._args_for_shared(linkflags) + [ '/EXPORT:$(PYPY_MAIN_FUNCTION)'] + linkflags += self._exportsymbols_link_flags(eci) if shared: so_name = exe_name.new(ext=self.so_ext) @@ -243,6 +254,7 @@ ('LDFLAGSEXTRA', list(eci.link_extra)), ('CC', self.cc), ('CC_LINK', self.link), + ('LINKFILES', eci.link_files), ('MASM', self.masm), ] @@ -262,7 +274,7 @@ '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS)') else: m.rule('$(TARGET)', '$(OBJECTS)', - ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) Modified: pypy/trunk/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/cbuild.py Fri Jun 11 15:22:37 2010 @@ -260,34 +260,6 @@ d['separate_module_files'] += tuple(files) return ExternalCompilationInfo(**d) - def convert_exportsymbols_to_file(self): - if not self.export_symbols: - return self - num = 0 - while 1: - file_name = udir.join('dynamic-symbols-%i' % num) - num += 1 - if not file_name.check(): - break - - # XXX this logic should be moved to translator/platform/*.py - d = self._copy_attributes() - f = file_name.open("w") - if host.name.startswith('darwin'): - for sym in self.export_symbols: - f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) - else: - f.write("{\n") - for sym in self.export_symbols: - f.write("%s;\n" % (sym,)) - f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) - f.close() - d['export_symbols'] = () - return ExternalCompilationInfo(**d) - - def get_module_files(self): d = self._copy_attributes() files = d['separate_module_files'] Modified: pypy/trunk/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/test/test_cbuild.py Fri Jun 11 15:22:37 2010 @@ -71,17 +71,6 @@ e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e - def test_convert_sources_to_c_files(self): - eci = ExternalCompilationInfo( - export_symbols=("foo", ) - ) - neweci = eci.convert_exportsymbols_to_file() - le = neweci.link_extra[-1] - assert "foo;" in file(le.rsplit("=", 1)[1]).read() - e = ExternalCompilationInfo() - assert e.convert_exportsymbols_to_file() is e - - def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' From antocuni at codespeak.net Fri Jun 11 15:34:00 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jun 2010 15:34:00 +0200 (CEST) Subject: [pypy-svn] r75270 - in pypy/branch/sys-prefix/pypy/doc: . config Message-ID: <20100611133400.B774D282BEC@codespeak.net> Author: antocuni Date: Fri Jun 11 15:33:58 2010 New Revision: 75270 Modified: pypy/branch/sys-prefix/pypy/doc/_ref.txt pypy/branch/sys-prefix/pypy/doc/coding-guide.txt pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.md5.txt pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.sha.txt pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.struct.txt pypy/branch/sys-prefix/pypy/doc/cpython_differences.txt pypy/branch/sys-prefix/pypy/doc/ctypes-implementation.txt pypy/branch/sys-prefix/pypy/doc/docindex.txt pypy/branch/sys-prefix/pypy/doc/getting-started-python.txt pypy/branch/sys-prefix/pypy/doc/maemo.txt pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt pypy/branch/sys-prefix/pypy/doc/sandbox.txt pypy/branch/sys-prefix/pypy/doc/stackless.txt Log: fix the docs for the new directory layout Modified: pypy/branch/sys-prefix/pypy/doc/_ref.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/_ref.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/_ref.txt Fri Jun 11 15:33:58 2010 @@ -1,7 +1,7 @@ .. _`demo/`: ../../demo .. _`demo/pickle_coroutine.py`: ../../demo/pickle_coroutine.py -.. _`lib-python/`: ../../lib-python -.. _`lib-python/2.5.2/dis.py`: ../../lib-python/2.5.2/dis.py +.. _`lib-python/`: ../../lib/pypy1.2/lib-python +.. _`lib-python/2.5.2/dis.py`: ../../lib/pypy1.2/lib-python/2.5.2/dis.py .. _`annotation/`: .. _`pypy/annotation`: ../../pypy/annotation .. _`pypy/annotation/annrpython.py`: ../../pypy/annotation/annrpython.py @@ -46,11 +46,10 @@ .. _`pypy/interpreter/astcompiler/ast.py`: ../../pypy/interpreter/astcompiler/ast.py .. _`pypy/interpreter/typedef.py`: ../../pypy/interpreter/typedef.py .. _`lib/`: -.. _`pypy/lib/`: ../../pypy/lib -.. _`lib/app_test/`: ../../pypy/lib/app_test -.. _`lib/distributed/`: ../../pypy/lib/distributed -.. _`pypy/lib/stackless.py`: ../../pypy/lib/stackless.py -.. _`pypy/lib/test2`: ../../pypy/lib/test2 +.. _`lib_pypy/`: ../../lib/pypy1.2/lib_pypy +.. _`lib/distributed/`: ../../lib/pypy1.2/lib_pypy/distributed +.. _`lib_pypy/stackless.py`: ../../lib/pypy1.2/lib_pypy/stackless.py +.. _`lib_pypy/pypy_test/`: ../../lib/pypy1.2/lib_pypy/pypy_test .. _`module/`: .. _`pypy/module`: .. _`pypy/module/`: ../../pypy/module Modified: pypy/branch/sys-prefix/pypy/doc/coding-guide.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/coding-guide.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/coding-guide.txt Fri Jun 11 15:33:58 2010 @@ -631,7 +631,7 @@ because they rely on implementation details of CPython. If we don't just modify an original CPython module but need to rewrite -it from scratch we put it into `pypy/lib/`_ as a pure application level +it from scratch we put it into `lib_pypy/`_ as a pure application level module. When we need access to interpreter-level objects we put the module into @@ -653,7 +653,7 @@ >>>> import operator >>>> operator.__file__ - '/home/hpk/pypy-dist/pypy/lib/operator.py' + '/home/hpk/pypy-dist/lib_pypy/operator.py' >>>> import opcode >>>> opcode.__file__ @@ -682,7 +682,7 @@ list of directories, specified in the ``PYTHONPATH`` environment variable. -*pypy/lib/* +*lib_pypy/* contains pure Python reimplementation of modules. @@ -794,14 +794,14 @@ --withoutmod-mymodule (the later being the default)) for py.py and translate.py. -Testing modules in ``pypy/lib`` +Testing modules in ``lib_pypy/`` -------------------------------- -You can go to the `pypy/lib/test2`_ directory and invoke the testing tool -("py.test" or "python ../../test_all.py") to run tests against the -pypy/lib hierarchy. Note, that tests in `pypy/lib/test2`_ are allowed +You can go to the `lib_pypy/pypy_test/`_ directory and invoke the testing tool +("py.test" or "python ../../pypy/test_all.py") to run tests against the +lib_pypy hierarchy. Note, that tests in `lib_pypy/pypy_test/`_ are allowed and encouraged to let their tests run at interpreter level although -`pypy/lib/`_ modules eventually live at PyPy's application level. +`lib_pypy/`_ modules eventually live at PyPy's application level. This allows us to quickly test our python-coded reimplementations against CPython. Modified: pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.md5.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.md5.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.md5.txt Fri Jun 11 15:33:58 2010 @@ -1,5 +1,5 @@ Use the built-in 'md5' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.sha.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.sha.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.sha.txt Fri Jun 11 15:33:58 2010 @@ -1,5 +1,5 @@ Use the built-in 'sha' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.struct.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.struct.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/config/objspace.usemodules.struct.txt Fri Jun 11 15:33:58 2010 @@ -1,5 +1,5 @@ Use the built-in 'struct' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/sys-prefix/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/cpython_differences.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/cpython_differences.txt Fri Jun 11 15:33:58 2010 @@ -71,7 +71,7 @@ _stackless * Supported by being rewritten in pure Python (possibly using ``ctypes``): - see the `pypy/lib/`_ directory. Examples of modules that we + see the `lib_pypy/`_ directory. Examples of modules that we support this way: ``ctypes``, ``array``, ``cPickle``, ``cStringIO``, ``cmath``, ``dbm`` (?), ``datetime``, ``binascii``... Note that some modules are both in there and in the list above; @@ -79,7 +79,7 @@ at translation time). The extension modules (i.e. modules written in C, in the standard CPython) -that are neither mentioned above nor in `pypy/lib/`_ are not available in PyPy. +that are neither mentioned above nor in `lib_pypy/`_ are not available in PyPy. .. the nonstandard modules are listed below... .. _`__pypy__`: __pypy__-module.html Modified: pypy/branch/sys-prefix/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/ctypes-implementation.txt Fri Jun 11 15:33:58 2010 @@ -48,9 +48,9 @@ High-level parts ================= -The reused ``ctypes`` package lives in ``pypy/lib/ctypes``. ``_ctypes`` +The reused ``ctypes`` package lives in ``lib_pypy/ctypes``. ``_ctypes`` implementing the same interface as ``_ctypes`` in CPython is in -``pypy/lib/_ctypes``. +``lib_pypy/_ctypes``. Discussion and limitations ============================= @@ -123,8 +123,8 @@ To run the tests then:: - $ cd ../.. # back to pypy/ - $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests + $ cd ../../.. # back to pypy-trunk + $ ./pypy/translator/goal/pypy-c pypy/test_all.py lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests There should be 36 skipped tests and all other tests should pass. Modified: pypy/branch/sys-prefix/pypy/doc/docindex.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/docindex.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/docindex.txt Fri Jun 11 15:33:58 2010 @@ -207,13 +207,6 @@ `interpreter/astcompiler/`_ interpreter-level bytecode compiler, via an AST representation -`lib/`_ PyPy's wholesale reimplementations of CPython modules_ - and experimental new application-level modules - -`lib/app_test/`_ tests for the reimplementations, running on top of CPython - -`lib/distributed/`_ distributed execution prototype, based on `transparent proxies`_ - `module/`_ contains `mixed modules`_ implementing core modules with both application and interpreter level code. Not all are finished and working. Use the ``--withmod-xxx`` Modified: pypy/branch/sys-prefix/pypy/doc/getting-started-python.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/getting-started-python.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/getting-started-python.txt Fri Jun 11 15:33:58 2010 @@ -207,18 +207,18 @@ For installation purposes, note that the executable needs to be able to find its version of the Python standard library in the following three directories: ``lib-python/2.5.2``, ``lib-python/modified-2.5.2`` and -``pypy/lib``. They are located by "looking around" starting from the +``lib_pypy``. They are located by "looking around" starting from the directory in which the executable resides. The current logic is to try to find a ``PREFIX`` from which the directories ``PREFIX/lib-python/2.5.2`` and ``PREFIX/lib-python/modified.2.5.2`` and -``PREFIX/pypy/lib`` can all be found. The prefixes that are tried are:: +``PREFIX/lib_pypy`` can all be found. The prefixes that are tried are:: . - ./share/pypy-1.2 + ./lib/pypy1.2 .. - ../share/pypy-1.2 + ../lib/pypy1.2 ../.. - ../../share/pypy-1.2 + ../../lib/pypy-1.2 ../../.. etc. Modified: pypy/branch/sys-prefix/pypy/doc/maemo.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/maemo.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/maemo.txt Fri Jun 11 15:33:58 2010 @@ -157,11 +157,11 @@ You can just copy your whole pypy-trunk directory over to your mobile device - however, only these should be needed:: - pypy/lib - lib-python + lib/pypy1.2/lib_pypy + lib/pypy1.2/lib-python pypy/translator/goal/pypy-c -It is neccessary that the ``pypy-c`` can find a "lib-python" and "pypy/lib" directory +It is neccessary that the ``pypy-c`` can find a "lib-python" and "lib_pypy" directory if you want to successfully startup the interpreter on the device. Start ``pypy-c`` on the device. If you see an error like "setupterm: could not find terminal" Modified: pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt Fri Jun 11 15:33:58 2010 @@ -610,7 +610,7 @@ .. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py .. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py .. _`transparent.py`: ../../pypy/objspace/std/transparent.py -.. _`tputil.py`: ../../pypy/lib/tputil.py +.. _`tputil.py`: ../../lib/pypy1.2/lib_pypy/tputil.py .. [D12.1] `High-Level Backends and Interpreter Feature Prototypes`, PyPy EU-Report, 2007, http://codespeak.net/pypy/extradoc/eu-report/D12.1_H-L-Backends_and_Feature_Prototypes-2007-03-22.pdf Modified: pypy/branch/sys-prefix/pypy/doc/sandbox.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/sandbox.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/sandbox.txt Fri Jun 11 15:33:58 2010 @@ -72,7 +72,8 @@ should do. I've successfully tried it on the JS interpreter. The controller is only called "pypy_interact" because it emulates a file hierarchy that makes pypy-c-sandbox happy - it contains (read-only) -virtual directories like /bin/lib-python and /bin/pypy/lib and it +virtual directories like /bin/lib/pypy1.2/lib-python and +/bin/lib/pypy1.2/lib_pypy and it pretends that the executable is /bin/pypy-c. Howto Modified: pypy/branch/sys-prefix/pypy/doc/stackless.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/stackless.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/stackless.txt Fri Jun 11 15:33:58 2010 @@ -181,7 +181,7 @@ website. Note that Tasklets and Channels are implemented at application-level in -`pypy/lib/stackless.py`_ on top of coroutines_. You can refer to this +`lib_pypy/stackless.py`_ on top of coroutines_. You can refer to this module for more details and API documentation. The stackless.py code tries to resemble the stackless C code as much From arigo at codespeak.net Fri Jun 11 15:56:06 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 15:56:06 +0200 (CEST) Subject: [pypy-svn] r75271 - in pypy/branch/multijit-3/pypy/jit/metainterp: . test Message-ID: <20100611135606.0EC6E282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 15:56:03 2010 New Revision: 75271 Modified: pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-3/pypy/jit/metainterp/compile.py pypy/branch/multijit-3/pypy/jit/metainterp/history.py pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-3/pypy/jit/metainterp/resume.py pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py pypy/branch/multijit-3/pypy/jit/metainterp/warmspot.py pypy/branch/multijit-3/pypy/jit/metainterp/warmstate.py Log: Tests start passing again. Modified: pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/blackhole.py Fri Jun 11 15:56:03 2010 @@ -315,27 +315,12 @@ def get_tmpreg_f(self): return self.tmpreg_f - def final_result_i(self): - assert self._return_type == 'i' - return self.get_tmpreg_i() - - def final_result_r(self): - assert self._return_type == 'r' - return self.get_tmpreg_r() - - def final_result_f(self): - assert self._return_type == 'f' - return self.get_tmpreg_f() - - def final_result_v(self): - assert self._return_type == 'v' - def _final_result_anytype(self): "NOT_RPYTHON" - if self._return_type == 'i': return self.final_result_i() - if self._return_type == 'r': return self.final_result_r() - if self._return_type == 'f': return self.final_result_f() - if self._return_type == 'v': return self.final_result_v() + if self._return_type == 'i': return self.get_tmpreg_i() + if self._return_type == 'r': return self.get_tmpreg_r() + if self._return_type == 'f': return self.get_tmpreg_v() + if self._return_type == 'v': return None raise ValueError(self._return_type) def cleanup_registers(self): @@ -790,6 +775,7 @@ # call the interpreter main loop from here, and just return its # result. sd = self.builder.metainterp_sd + xxxxxxxxxxxx if sd.result_type == 'void': self.bhimpl_recursive_call_v(jdindex, *args) self.bhimpl_void_return() @@ -1176,11 +1162,11 @@ self._done_with_this_frame() kind = self._return_type if kind == 'i': - caller._setup_return_value_i(self.final_result_i()) + caller._setup_return_value_i(self.get_tmpreg_i()) elif kind == 'r': - caller._setup_return_value_r(self.final_result_r()) + caller._setup_return_value_r(self.get_tmpreg_r()) elif kind == 'f': - caller._setup_return_value_f(self.final_result_f()) + caller._setup_return_value_f(self.get_tmpreg_f()) else: assert kind == 'v' return lltype.nullptr(rclass.OBJECTPTR.TO) @@ -1246,15 +1232,15 @@ # rare case: we only get there if the blackhole interps all returned # normally (in general we get a ContinueRunningNormally exception). sd = self.builder.metainterp_sd - if sd.result_type == 'void': - self.final_result_v() + kind = self._return_type + if kind == 'v': raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': - raise sd.DoneWithThisFrameInt(self.final_result_i()) - elif sd.result_type == 'ref': - raise sd.DoneWithThisFrameRef(self.cpu, self.final_result_r()) - elif sd.result_type == 'float': - raise sd.DoneWithThisFrameFloat(self.final_result_f()) + elif kind == 'i': + raise sd.DoneWithThisFrameInt(self.get_tmpreg_i()) + elif kind == 'r': + raise sd.DoneWithThisFrameRef(self.cpu, self.get_tmpreg_r()) + elif kind == 'f': + raise sd.DoneWithThisFrameFloat(self.get_tmpreg_f()) else: assert False @@ -1288,12 +1274,14 @@ blackholeinterp.builder.release_interp(blackholeinterp) blackholeinterp = blackholeinterp.nextblackholeinterp -def resume_in_blackhole(metainterp_sd, resumedescr, all_virtuals=None): +def resume_in_blackhole(metainterp_sd, jitdriver_sd, resumedescr, + all_virtuals=None): from pypy.jit.metainterp.resume import blackhole_from_resumedata debug_start('jit-blackhole') metainterp_sd.profiler.start_blackhole() blackholeinterp = blackhole_from_resumedata( metainterp_sd.blackholeinterpbuilder, + jitdriver_sd, resumedescr, all_virtuals) current_exc = blackholeinterp._prepare_resume_from_failure( Modified: pypy/branch/multijit-3/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/compile.py Fri Jun 11 15:56:03 2010 @@ -63,11 +63,12 @@ # make a copy, because optimize_loop can mutate the ops and descrs loop.operations = [op.clone() for op in ops] metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd loop_token = make_loop_token(len(loop.inputargs)) loop.token = loop_token loop.operations[-1].descr = loop_token # patch the target of the JUMP try: - old_loop_token = metainterp_sd.state.optimize_loop( + old_loop_token = jitdriver_sd._state.optimize_loop( metainterp_sd, old_loop_tokens, loop) except InvalidLoop: return None @@ -141,32 +142,32 @@ pass class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'void' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.VOID raise metainterp_sd.DoneWithThisFrameVoid() class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'int' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.INT result = metainterp_sd.cpu.get_latest_value_int(0) raise metainterp_sd.DoneWithThisFrameInt(result) class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'ref' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.REF cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'float' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.FLOAT result = metainterp_sd.cpu.get_latest_value_float(0) raise metainterp_sd.DoneWithThisFrameFloat(result) class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) @@ -258,22 +259,27 @@ # a negative value self._counter = cnt | i - def handle_fail(self, metainterp_sd): - if self.must_compile(metainterp_sd): - return self._trace_and_compile_from_bridge(metainterp_sd) + def handle_fail(self, metainterp_sd, jitdriver_sd): + if self.must_compile(metainterp_sd, jitdriver_sd): + return self._trace_and_compile_from_bridge(metainterp_sd, + jitdriver_sd) else: from pypy.jit.metainterp.blackhole import resume_in_blackhole - resume_in_blackhole(metainterp_sd, self) + resume_in_blackhole(metainterp_sd, jitdriver_sd, self) assert 0, "unreachable" - def _trace_and_compile_from_bridge(self, metainterp_sd): + def _trace_and_compile_from_bridge(self, metainterp_sd, jitdriver_sd): + # 'jitdriver_sd' corresponds to the outermost one, i.e. the one + # of the jit_merge_point where we started the loop, even if the + # loop itself may contain temporarily recursion into other + # jitdrivers. from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) return metainterp.handle_guard_failure(self) _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd): - trace_eagerness = metainterp_sd.state.trace_eagerness + def must_compile(self, metainterp_sd, jitdriver_sd): + trace_eagerness = jitdriver_sd._state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness @@ -333,7 +339,7 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): # Failures of a GUARD_NOT_FORCED are never compiled, but # always just blackholed. First fish for the data saved when # the virtualrefs and virtualizable have been forced by @@ -343,7 +349,7 @@ all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - resume_in_blackhole(metainterp_sd, self, all_virtuals) + resume_in_blackhole(metainterp_sd, jitdriver_sd, self, all_virtuals) assert 0, "unreachable" @staticmethod @@ -464,6 +470,7 @@ # a loop at all but ends in a jump to the target loop. It starts # with completely unoptimized arguments, as in the interpreter. metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd metainterp.history.inputargs = self.redkey new_loop_token = make_loop_token(len(self.redkey)) new_loop.greenkey = self.original_greenkey @@ -471,12 +478,11 @@ new_loop.token = new_loop_token send_loop_to_backend(metainterp_sd, new_loop, "entry bridge") # send the new_loop to warmspot.py, to be called directly the next time - metainterp_sd.state.attach_unoptimized_bridge_from_interp( + jitdriver_sd._state.attach_unoptimized_bridge_from_interp( self.original_greenkey, new_loop_token) # store the new loop in compiled_merge_points too - glob = metainterp_sd.globaldata - old_loop_tokens = glob.get_compiled_merge_points( + old_loop_tokens = metainterp.get_compiled_merge_points( self.original_greenkey) # it always goes at the end of the list, as it is the most # general loop token @@ -500,8 +506,9 @@ # clone ops, as optimize_bridge can mutate the ops new_loop.operations = [op.clone() for op in metainterp.history.operations] metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd try: - target_loop_token = metainterp_sd.state.optimize_bridge(metainterp_sd, + target_loop_token = jitdriver_sd._state.optimize_bridge(metainterp_sd, old_loop_tokens, new_loop) except InvalidLoop: Modified: pypy/branch/multijit-3/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/history.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/history.py Fri Jun 11 15:56:03 2010 @@ -174,7 +174,7 @@ class AbstractFailDescr(AbstractDescr): index = -1 - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): raise NotImplementedError def compile_and_attach(self, metainterp, new_loop): raise NotImplementedError Modified: pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py Fri Jun 11 15:56:03 2010 @@ -13,5 +13,7 @@ # self.index ... pypy.jit.codewriter.call # self.mainjitcode ... pypy.jit.codewriter.call + # warmspot sets extra attributes starting with '_' for its own use. + def _freeze_(self): return True Modified: pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 15:56:03 2010 @@ -557,6 +557,7 @@ def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) + xxxxxxx vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -606,6 +607,7 @@ arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, fdescr, box) return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) + xxxxxxx vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -655,8 +657,8 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("boxes3", "boxes3") - def _opimpl_recursive_call(self, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): allboxes = greenboxes + redboxes metainterp_sd = self.metainterp.staticdata xxxx @@ -766,17 +768,18 @@ raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args + def verify_green_args(self, jdindex, varargs): + jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] + num_green_args = jitdriver.num_green_args assert len(varargs) == num_green_args for i in range(num_green_args): assert isinstance(varargs[i], Const) - @arguments("orgpc", "boxes3", "boxes3") - def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): - self.verify_green_args(greenboxes) + @arguments("orgpc", "int", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes): + self.verify_green_args(jdindex, greenboxes) # xxx we may disable the following line in some context later - self.debug_merge_point(greenboxes) + self.debug_merge_point(jdindex, greenboxes) if self.metainterp.seen_can_enter_jit: self.metainterp.seen_can_enter_jit = False # Assert that it's impossible to arrive here with in_recursion @@ -784,6 +787,7 @@ # to True by opimpl_can_enter_jit, which should be executed # just before opimpl_jit_merge_point (no recursion inbetween). assert not self.metainterp.in_recursion + assert jdindex == self.metainterp.jitdriver_sd.index # Set self.pc to point to jit_merge_point instead of just after: # if reached_can_enter_jit() raises SwitchToBlackhole, then the # pc is still at the jit_merge_point, which is a point that is @@ -793,10 +797,10 @@ self.metainterp.reached_can_enter_jit(greenboxes, redboxes) self.pc = saved_pc - def debug_merge_point(self, greenkey): + def debug_merge_point(self, jdindex, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - sd = self.metainterp.staticdata - loc = sd.state.get_location_str(greenkey) + jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] + loc = jitdriver._state.get_location_str(greenkey) debug_print(loc) constloc = self.metainterp.cpu.ts.conststr(loc) self.metainterp.history.record(rop.DEBUG_MERGE_POINT, @@ -1131,6 +1135,11 @@ self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] + def setup_jitdrivers_sd(self, optimizer): + if optimizer is not None: + for jd in self.jitdrivers_sd: + jd._state.set_param_optimizer(optimizer) + def finish_setup(self, codewriter, optimizer=None): from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) @@ -1143,14 +1152,8 @@ # self.jitdrivers_sd = codewriter.callcontrol.jitdrivers_sd self.virtualref_info = codewriter.callcontrol.virtualref_info + self.setup_jitdrivers_sd(optimizer) # - warmrunnerdesc = self.warmrunnerdesc - if warmrunnerdesc is not None: - XXX - self.num_green_args = warmrunnerdesc.num_green_args - self.state = warmrunnerdesc.state - if optimizer is not None: - self.state.set_param_optimizer(optimizer) self.globaldata = MetaInterpGlobalData(self) def _setup_once(self): @@ -1229,34 +1232,19 @@ self.loopnumbering = 0 self.resume_virtuals = {} self.resume_virtuals_not_translated = [] - # - state = None # XXX staticdata.state - if state is not None: - self.jit_cell_at_key = state.jit_cell_at_key - else: - # for tests only; not RPython - class JitCell: - compiled_merge_points = None - _jitcell_dict = {} - def jit_cell_at_key(greenkey): - greenkey = tuple(greenkey) - return _jitcell_dict.setdefault(greenkey, JitCell()) - self.jit_cell_at_key = jit_cell_at_key - - def get_compiled_merge_points(self, greenkey): - cell = self.jit_cell_at_key(greenkey) - if cell.compiled_merge_points is None: - cell.compiled_merge_points = [] - return cell.compiled_merge_points # ____________________________________________________________ class MetaInterp(object): in_recursion = 0 - def __init__(self, staticdata): + def __init__(self, staticdata, jitdriver_sd): self.staticdata = staticdata self.cpu = staticdata.cpu + self.jitdriver_sd = jitdriver_sd + # Note: self.jitdriver_sd is the JitDriverStaticData that corresponds + # to the current loop -- the outermost one. Be careful, because + # during recursion we can also see other jitdrivers. self.portal_trace_positions = [] self.free_frames_list = [] self.last_exc_value_box = None @@ -1363,7 +1351,6 @@ raise AssertionError def create_empty_history(self): - warmrunnerstate = self.staticdata.state self.history = history.History() self.staticdata.stats.set_history(self.history) @@ -1473,12 +1460,11 @@ self.resumekey.reset_counter_from_failure() def blackhole_if_trace_too_long(self): - warmrunnerstate = self.staticdata.state + warmrunnerstate = self.jitdriver_sd._state if len(self.history.operations) > warmrunnerstate.trace_limit: greenkey_of_huge_function = self.find_biggest_function() self.portal_trace_positions = None if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state warmrunnerstate.disable_noninlinable_function( greenkey_of_huge_function) raise SwitchToBlackhole(ABORT_TOO_LONG) @@ -1507,13 +1493,16 @@ @specialize.arg(1) def compile_and_run_once(self, jitdriver_sd, *args): + # NB. we pass explicity 'jitdriver_sd' around here, even though it + # is also available as 'self.jitdriver_sd', because we need to + # specialize this function and a few other ones for the '*args'. debug_start('jit-tracing') self.staticdata._setup_once() self.staticdata.profiler.start_tracing() + assert jitdriver_sd is self.jitdriver_sd self.create_empty_history() try: original_boxes = self.initialize_original_boxes(jitdriver_sd,*args) - self.jitdriver_sd = jitdriver_sd return self._compile_and_run_once(original_boxes) finally: self.staticdata.profiler.end_tracing() @@ -1611,11 +1600,12 @@ # Search in current_merge_points for original_boxes with compatible # green keys, representing the beginning of the same loop as the one # we end now. - + + num_green_args = self.jitdriver_sd.num_green_args for j in range(len(self.current_merge_points)-1, -1, -1): original_boxes, start = self.current_merge_points[j] assert len(original_boxes) == len(live_arg_boxes) or start < 0 - for i in range(self.staticdata.num_green_args): + for i in range(num_green_args): box1 = original_boxes[i] box2 = live_arg_boxes[i] assert isinstance(box1, Const) @@ -1638,7 +1628,7 @@ def designate_target_loop(self, gmp): loop_token = gmp.target_loop_token - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args residual_args = self.get_residual_args(loop_token.specnodes, gmp.argboxes[num_green_args:]) history.set_future_values(self.cpu, residual_args) @@ -1679,12 +1669,17 @@ from pypy.jit.metainterp.resoperation import opname raise NotImplementedError(opname[opnum]) + def get_compiled_merge_points(self, greenkey): + cell = self.jitdriver_sd._state.jit_cell_at_key(greenkey) + if cell.compiled_merge_points is None: + cell.compiled_merge_points = [] + return cell.compiled_merge_points + def compile(self, original_boxes, live_arg_boxes, start): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop_token = compile.compile_new_loop(self, old_loop_tokens, greenkey, start) @@ -1693,10 +1688,9 @@ self.history.operations.pop() # remove the JUMP def compile_bridge(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args greenkey = live_arg_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) if len(old_loop_tokens) == 0: return self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) @@ -1755,9 +1749,6 @@ @specialize.arg(1) def initialize_original_boxes(self, jitdriver_sd, *args): - # NB. we pass explicity 'jitdriver_sd' around here, even though it - # might also available as 'self.jitdriver_sd', because we need to - # specialize these functions for the particular *args. original_boxes = [] self._fill_original_boxes(jitdriver_sd, original_boxes, jitdriver_sd.num_green_args, *args) @@ -2164,6 +2155,16 @@ position = position3 + 1 + length3 elif argtype == "orgpc": value = orgpc + elif argtype == "int": + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = ord(code[position]) + elif argcode == 'c': + value = signedord(code[position]) + else: + raise AssertionError("bad argcode") + position += 1 else: raise AssertionError("bad argtype: %r" % (argtype,)) args += (value,) Modified: pypy/branch/multijit-3/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/resume.py Fri Jun 11 15:56:03 2010 @@ -709,11 +709,11 @@ # ---------- when resuming for blackholing, get direct values ---------- -def blackhole_from_resumedata(blackholeinterpbuilder, storage, +def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage, all_virtuals=None): resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, all_virtuals) - vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vinfo = jitdriver_sd.virtualizable_info vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info resumereader.consume_vref_and_vable(vrefinfo, vinfo) # Modified: pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 15:56:03 2010 @@ -16,10 +16,18 @@ from pypy.jit.codewriter import support, codewriter from pypy.jit.metainterp import simple_optimize + class FakeJitCell: + compiled_merge_points = None + class FakeWarmRunnerState: def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): pass + def jit_cell_at_key(self, greenkey): + assert greenkey == [] + return self._cell + _cell = FakeJitCell() + # pick the optimizer this way optimize_loop = staticmethod(simple_optimize.optimize_loop) optimize_bridge = staticmethod(simple_optimize.optimize_bridge) @@ -45,7 +53,7 @@ testself.cw = cw cw.find_all_graphs(JitPolicy()) # - testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate = FakeJitDriverSD._state = FakeWarmRunnerState() testself.warmrunnerstate.cpu = cpu if hasattr(testself, 'finish_setup_for_interp_operations'): testself.finish_setup_for_interp_operations() @@ -88,15 +96,13 @@ cw = testself.cw opt = history.Options(listops=True) metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) - metainterp_sd.finish_setup(cw, optimizer="bogus") - metainterp_sd.state = testself.warmrunnerstate - metainterp_sd.state.cpu = metainterp_sd.cpu - metainterp = pyjitpl.MetaInterp(metainterp_sd) + metainterp_sd.finish_setup(cw) + [jitdriver_sd] = metainterp_sd.jitdrivers_sd + metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd) metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame testself.metainterp = metainterp - [jitdriver_sd] = cw.callcontrol.jitdrivers_sd try: metainterp.compile_and_run_once(jitdriver_sd, *args) except DoneWithThisFrame, e: @@ -802,8 +808,9 @@ translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=self.CPUClass) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(0) # for tests + state = warmrunnerdesc.jitdrivers_sd[0]._state + state.set_param_threshold(3) # for tests + state.set_param_trace_eagerness(0) # for tests warmrunnerdesc.finish() for n, k in [(20, 0), (20, 1)]: interp.eval_graph(graph, [n, k]) Modified: pypy/branch/multijit-3/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/warmspot.py Fri Jun 11 15:56:03 2010 @@ -21,6 +21,7 @@ from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.metainterp.jitdriver import JitDriverStaticData from pypy.jit.codewriter import support, codewriter from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE @@ -69,11 +70,12 @@ translator.config.translation.gc = "boehm" translator.config.translation.list_comprehension_operations = True warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests - warmrunnerdesc.state.set_param_trace_limit(trace_limit) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_debug(debug_level) + for jd in warmrunnerdesc.jitdrivers_sd: + jd._state.set_param_threshold(3) # for tests + jd._state.set_param_trace_eagerness(2) # for tests + jd._state.set_param_trace_limit(trace_limit) + jd._state.set_param_inlining(inline) + jd._state.set_param_debug(debug_level) warmrunnerdesc.finish() res = interp.eval_graph(graph, args) if not kwds.get('translate_support_code', False): @@ -110,12 +112,11 @@ raise Exception("no can_enter_jit found!") return results -def find_jit_merge_point(graphs): +def find_jit_merge_points(graphs): results = _find_jit_marker(graphs, 'jit_merge_point') - if len(results) != 1: - raise Exception("found %d jit_merge_points, need exactly one!" % - (len(results),)) - return results[0] + if not results: + raise Exception("no jit_merge_point found!") + return results def find_set_param(graphs): return _find_jit_marker(graphs, 'set_param') @@ -146,8 +147,8 @@ pyjitpl._warmrunnerdesc = self # this is a global for debugging only! self.set_translator(translator) self.build_cpu(CPUClass, **kwds) - self.find_portal() - self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + self.find_portals() + self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd) if policy is None: policy = JitPolicy() policy.set_supports_floats(self.cpu.supports_floats) @@ -158,35 +159,31 @@ self.prejit_optimizations(policy, graphs) self.build_meta_interp(ProfilerClass) - self.make_args_specification() + self.make_args_specifications() # from pypy.jit.metainterp.virtualref import VirtualRefInfo vrefinfo = VirtualRefInfo(self) self.codewriter.setup_vrefinfo(vrefinfo) - if self.jitdriver.virtualizables: - from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.virtualizable_info = VirtualizableInfo(self) - self.codewriter.setup_virtualizable_info(self.virtualizable_info) - else: - self.virtualizable_info = None # + self.make_virtualizable_infos() self.make_exception_classes() self.make_driverhook_graphs() - self.make_enter_function() - self.rewrite_jit_merge_point(policy) + self.make_enter_functions() + self.rewrite_jit_merge_points(policy) verbose = not self.cpu.translate_support_code self.codewriter.make_jitcodes(verbose=verbose) - self.rewrite_can_enter_jit() + self.rewrite_can_enter_jits() self.rewrite_set_param() self.rewrite_force_virtual(vrefinfo) self.add_finish() self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.virtualizable_info - if vinfo is not None: - vinfo.finish() + vinfos = set([jd.virtualizable_info for jd in self.jitdrivers_sd]) + for vinfo in vinfos: + if vinfo is not None: + vinfo.finish() if self.cpu.translate_support_code: self.annhelper.finish() @@ -198,18 +195,27 @@ self.rtyper = translator.rtyper self.gcdescr = gc.get_description(translator.config) - def find_portal(self): + def find_portals(self): + self.jitdrivers_sd = [] graphs = self.translator.graphs - self.jit_merge_point_pos = find_jit_merge_point(graphs) - graph, block, pos = self.jit_merge_point_pos + for jit_merge_point_pos in find_jit_merge_points(graphs): + self.split_graph_and_record_jitdriver(*jit_merge_point_pos) + # + assert (len(set([jd.jitdriver for jd in self.jitdrivers_sd])) == + len(self.jitdrivers_sd)), \ + "there are multiple jit_merge_points with the same jitdriver" + + def split_graph_and_record_jitdriver(self, graph, block, pos): + jd = JitDriverStaticData() + jd._jit_merge_point_pos = (graph, block, pos) op = block.operations[pos] args = op.args[2:] s_binding = self.translator.annotator.binding - self.portal_args_s = [s_binding(v) for v in args] + jd._portal_args_s = [s_binding(v) for v in args] graph = copygraph(graph) graph.startblock.isstartblock = False - graph.startblock = support.split_before_jit_merge_point( - *find_jit_merge_point([graph])) + [jmpp] = find_jit_merge_points([graph]) + graph.startblock = support.split_before_jit_merge_point(*jmpp) graph.startblock.isstartblock = True # a crash in the following checkgraph() means that you forgot # to list some variable in greens=[] or reds=[] in JitDriver. @@ -218,12 +224,16 @@ assert isinstance(v, Variable) assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs()) self.translator.graphs.append(graph) - self.portal_graph = graph + jd.portal_graph = graph # it's a bit unbelievable to have a portal without func assert hasattr(graph, "func") graph.func._dont_inline_ = True graph.func._jit_unroll_safe_ = True - self.jitdriver = block.operations[pos].args[1].value + jd.jitdriver = block.operations[pos].args[1].value + jd.portal_runner_ptr = "" + jd.result_type = history.getkind(jd.portal_graph.getreturnvar() + .concretetype)[0] + self.jitdrivers_sd.append(jd) def check_access_directly_sanity(self, graphs): from pypy.translator.backendopt.inline import collect_called_graphs @@ -268,6 +278,17 @@ ProfilerClass=ProfilerClass, warmrunnerdesc=self) + def make_virtualizable_infos(self): + for jd in self.jitdrivers_sd: + if jd.jitdriver.virtualizables: + XXX + from pypy.jit.metainterp.virtualizable import VirtualizableInfo + vinfo = VirtualizableInfo(self) + YYY # share! + else: + vinfo = None + jd.virtualizable_info = vinfo + def make_exception_classes(self): class DoneWithThisFrameVoid(JitException): @@ -317,6 +338,8 @@ self.green_int, self.green_ref, self.green_float, self.red_int, self.red_ref, self.red_float) + # XXX there is no point any more to not just have the exceptions + # as globals self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt self.DoneWithThisFrameRef = DoneWithThisFrameRef @@ -330,11 +353,15 @@ self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally - def make_enter_function(self): + def make_enter_functions(self): + for jd in self.jitdrivers_sd: + self.make_enter_function(jd) + + def make_enter_function(self, jd): from pypy.jit.metainterp.warmstate import WarmEnterState - state = WarmEnterState(self) + state = WarmEnterState(self, jd) maybe_compile_and_run = state.make_entry_point() - self.state = state + jd._state = state def crash_in_jit(e): if not we_are_translated(): @@ -359,15 +386,16 @@ def maybe_enter_jit(*args): maybe_compile_and_run(*args) maybe_enter_jit._always_inline_ = True - self.maybe_enter_jit_fn = maybe_enter_jit + jd._maybe_enter_jit_fn = maybe_enter_jit - can_inline = self.state.can_inline_greenargs + can_inline = state.can_inline_greenargs + num_green_args = jd.num_green_args def maybe_enter_from_start(*args): - if can_inline is not None and not can_inline(*args[:self.num_green_args]): + if can_inline is not None and not can_inline(*args[:num_green_args]): maybe_compile_and_run(*args) maybe_enter_from_start._always_inline_ = True - self.maybe_enter_from_start_fn = maybe_enter_from_start - + jd._maybe_enter_from_start_fn = maybe_enter_from_start + def make_driverhook_graphs(self): from pypy.rlib.jit import BaseJitCell bk = self.rtyper.annotator.bookkeeper @@ -378,22 +406,23 @@ s_Str = annmodel.SomeString() # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) - self.set_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.set_jitcell_at, annmodel.s_None, - s_BaseJitCell_not_None) - self.get_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) - self.can_inline_ptr = self._make_hook_graph( - annhelper, self.jitdriver.can_inline, annmodel.s_Bool) - self.get_printable_location_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_printable_location, s_Str) - self.confirm_enter_jit_ptr = self._make_hook_graph( - annhelper, self.jitdriver.confirm_enter_jit, annmodel.s_Bool, - onlygreens=False) + for jd in self.jitdrivers_sd: + jd._set_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.set_jitcell_at, annmodel.s_None, + s_BaseJitCell_not_None) + jd._get_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) + jd._can_inline_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.can_inline, annmodel.s_Bool) + jd._get_printable_location_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_printable_location, s_Str) + jd._confirm_enter_jit_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, + onlygreens=False) annhelper.finish() - def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None, - onlygreens=True): + def _make_hook_graph(self, jitdriver_sd, annhelper, func, + s_result, s_first_arg=None, onlygreens=True): if func is None: return None # @@ -401,38 +430,57 @@ if s_first_arg is not None: extra_args_s.append(s_first_arg) # - args_s = self.portal_args_s + args_s = jitdriver_sd._portal_args_s if onlygreens: - args_s = args_s[:len(self.green_args_spec)] + args_s = args_s[:len(jitdriver_sd._green_args_spec)] graph = annhelper.getgraph(func, extra_args_s + args_s, s_result) funcptr = annhelper.graph2delayed(graph) return funcptr - def make_args_specification(self): - graph, block, index = self.jit_merge_point_pos + def make_args_specifications(self): + for jd in self.jitdrivers_sd: + self.make_args_specification(jd) + + def make_args_specification(self, jd): + graph, block, index = jd._jit_merge_point_pos op = block.operations[index] greens_v, reds_v = support.decode_hp_hint_args(op) ALLARGS = [v.concretetype for v in (greens_v + reds_v)] - self.green_args_spec = [v.concretetype for v in greens_v] - self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] - self.num_green_args = len(self.green_args_spec) + jd._green_args_spec = [v.concretetype for v in greens_v] + jd._red_args_types = [history.getkind(v.concretetype) for v in reds_v] + jd.num_green_args = len(jd._green_args_spec) RESTYPE = graph.getreturnvar().concretetype - (self.JIT_ENTER_FUNCTYPE, - self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) - (self.PORTAL_FUNCTYPE, - self.PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) - (_, self.PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( + (jd._JIT_ENTER_FUNCTYPE, + jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) + (jd._PORTAL_FUNCTYPE, + jd._PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) + (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( [lltype.Signed, llmemory.GCREF], RESTYPE) - def rewrite_can_enter_jit(self): - FUNC = self.JIT_ENTER_FUNCTYPE - FUNCPTR = self.PTR_JIT_ENTER_FUNCTYPE - jit_enter_fnptr = self.helper_func(FUNCPTR, self.maybe_enter_jit_fn) + def rewrite_can_enter_jits(self): + can_enter_jits = find_can_enter_jit(self.translator.graphs) + sublists = {} + for jd in self.jitdrivers_sd: + sublists[jd.jitdriver] = [] + for graph, block, index in can_enter_jits: + op = block.operations[index] + jitdriver = op.args[1].value + assert jitdriver in sublists, \ + "can_enter_jit with no matching jit_merge_point" + sublists[jitdriver].append((graph, block, index)) + for jd in self.jitdrivers_sd: + sublist = sublists[jd.jitdriver] + assert len(sublist) > 0, \ + "found no can_enter_jit for %r" % (jd.jitdriver,) + self.rewrite_can_enter_jit(jd, sublist) + + def rewrite_can_enter_jit(self, jd, can_enter_jits): + FUNC = jd._JIT_ENTER_FUNCTYPE + FUNCPTR = jd._PTR_JIT_ENTER_FUNCTYPE + jit_enter_fnptr = self.helper_func(FUNCPTR, jd._maybe_enter_jit_fn) - graphs = self.translator.graphs - can_enter_jits = find_can_enter_jit(graphs) for graph, block, index in can_enter_jits: - if graph is self.jit_merge_point_pos[0]: + if graph is jd._jit_merge_point_pos[0]: continue op = block.operations[index] @@ -455,7 +503,11 @@ graph = self.annhelper.getgraph(func, args_s, s_result) return self.annhelper.graph2delayed(graph, FUNC) - def rewrite_jit_merge_point(self, policy): + def rewrite_jit_merge_points(self, policy): + for jd in self.jitdrivers_sd: + self.rewrite_jit_merge_point(jd, policy) + + def rewrite_jit_merge_point(self, jd, policy): # # Mutate the original portal graph from this: # @@ -486,9 +538,9 @@ # while 1: # more stuff # - origportalgraph = self.jit_merge_point_pos[0] - portalgraph = self.portal_graph - PORTALFUNC = self.PORTAL_FUNCTYPE + origportalgraph = jd._jit_merge_point_pos[0] + portalgraph = jd.portal_graph + PORTALFUNC = jd._PORTAL_FUNCTYPE # ____________________________________________________________ # Prepare the portal_runner() helper @@ -496,12 +548,12 @@ from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) - self.portal_ptr = portal_ptr + jd._portal_ptr = portal_ptr # portalfunc_ARGS = [] nums = {} for i, ARG in enumerate(PORTALFUNC.ARGS): - if i < len(self.jitdriver.greens): + if i < len(jd.jitdriver.greens): color = 'green' else: color = 'red' @@ -519,7 +571,7 @@ def ll_portal_runner(*args): while 1: try: - self.maybe_enter_from_start_fn(*args) + jd._maybe_enter_from_start_fn(*args) return support.maybe_on_top_of_llinterp(rtyper, portal_ptr)(*args) except self.ContinueRunningNormally, e: @@ -548,16 +600,15 @@ value = cast_base_ptr_to_instance(Exception, value) raise Exception, value - self.ll_portal_runner = ll_portal_runner # for debugging - self.portal_runner_ptr = self.helper_func(self.PTR_PORTAL_FUNCTYPE, - ll_portal_runner) + jd._ll_portal_runner = ll_portal_runner # for debugging + jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE, + ll_portal_runner) self.cpu.portal_calldescr = self.cpu.calldescrof( - self.PTR_PORTAL_FUNCTYPE.TO, - self.PTR_PORTAL_FUNCTYPE.TO.ARGS, - self.PTR_PORTAL_FUNCTYPE.TO.RESULT) - self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) + jd._PTR_PORTAL_FUNCTYPE.TO, + jd._PTR_PORTAL_FUNCTYPE.TO.ARGS, + jd._PTR_PORTAL_FUNCTYPE.TO.RESULT) - vinfo = self.virtualizable_info + vinfo = jd.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -567,6 +618,7 @@ virtualizable = lltype.cast_opaque_ptr( vinfo.VTYPEPTR, virtualizableref) vinfo.reset_vable_token(virtualizable) + XXX # careful here, we must pass the correct jitdriver_sd loop_token = fail_descr.handle_fail(self.metainterp_sd) fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: @@ -596,12 +648,14 @@ value = cast_base_ptr_to_instance(Exception, value) raise Exception, value - self.assembler_call_helper = assembler_call_helper # for debugging + jd._assembler_call_helper = assembler_call_helper # for debugging + # XXX rewrite me, ugly sticking does not work any more self.cpu.assembler_helper_ptr = self.helper_func( - self.PTR_ASSEMBLER_HELPER_FUNCTYPE, + jd._PTR_ASSEMBLER_HELPER_FUNCTYPE, assembler_call_helper) # XXX a bit ugly sticking if vinfo is not None: + XXX # rewrite me, ugly sticking does not work any more self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) else: @@ -610,12 +664,12 @@ # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr # - _, origblock, origindex = self.jit_merge_point_pos + _, origblock, origindex = jd._jit_merge_point_pos op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' greens_v, reds_v = support.decode_hp_hint_args(op) - vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] + vlist = [Constant(jd.portal_runner_ptr, jd._PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v v_result = Variable() @@ -642,8 +696,8 @@ graphs = self.translator.graphs _, PTR_SET_PARAM_FUNCTYPE = self.cpu.ts.get_FuncType([lltype.Signed], lltype.Void) - def make_closure(fullfuncname): - state = self.state + def make_closure(jd, fullfuncname): + state = jd._state def closure(i): getattr(state, fullfuncname)(i) funcptr = self.helper_func(PTR_SET_PARAM_FUNCTYPE, closure) @@ -651,12 +705,17 @@ # for graph, block, i in find_set_param(graphs): op = block.operations[i] - assert op.args[1].value == self.jitdriver + for jd in self.jitdrivers_sd: + if jd.jitdriver is op.args[1].value: + break + else: + assert 0, "jitdriver of set_param() not found" funcname = op.args[2].value - if funcname not in closures: - closures[funcname] = make_closure('set_param_' + funcname) + key = jd, funcname + if key not in closures: + closures[key] = make_closure(jd, 'set_param_' + funcname) op.opname = 'direct_call' - op.args[:3] = [closures[funcname]] + op.args[:3] = [closures[key]] def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': Modified: pypy/branch/multijit-3/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/multijit-3/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/multijit-3/pypy/jit/metainterp/warmstate.py Fri Jun 11 15:56:03 2010 @@ -1,7 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.rpython.ootypesystem import ootype -from pypy.rpython.annlowlevel import hlstr, cast_base_ptr_to_instance +from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance from pypy.rpython.annlowlevel import cast_object_to_ptr from pypy.rlib.objectmodel import specialize, we_are_translated, r_dict from pypy.rlib.rarithmetic import intmask @@ -120,6 +120,16 @@ else: assert False +class JitCell(BaseJitCell): + # the counter can mean the following things: + # counter >= 0: not yet traced, wait till threshold is reached + # counter == -1: there is an entry bridge for this cell + # counter == -2: tracing is currently going on for this cell + counter = 0 + compiled_merge_points = None + dont_trace_here = False + entry_loop_token = None + # ____________________________________________________________ @@ -127,9 +137,10 @@ THRESHOLD_LIMIT = sys.maxint // 2 default_jitcell_dict = None - def __init__(self, warmrunnerdesc): + def __init__(self, warmrunnerdesc, jitdriver_sd): "NOT_RPYTHON" self.warmrunnerdesc = warmrunnerdesc + self.jitdriver_sd = jitdriver_sd try: self.profiler = warmrunnerdesc.metainterp_sd.profiler except AttributeError: # for tests @@ -195,8 +206,9 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = self.warmrunnerdesc.virtualizable_info - num_green_args = self.warmrunnerdesc.num_green_args + jitdriver_sd = self.jitdriver_sd + vinfo = jitdriver_sd.virtualizable_info + num_green_args = jitdriver_sd.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() self.make_jitdriver_callbacks() @@ -206,7 +218,6 @@ """Entry point to the JIT. Called at the point with the can_enter_jit() hint. """ - globaldata = metainterp_sd.globaldata if NonConstant(False): # make sure we always see the saner optimizer from an # annotation point of view, otherwise we get lots of @@ -234,11 +245,12 @@ return # bound reached; start tracing from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) # set counter to -2, to mean "tracing in effect" cell.counter = -2 try: - loop_token = metainterp.compile_and_run_once(*args) + loop_token = metainterp.compile_and_run_once(jitdriver_sd, + *args) finally: if cell.counter == -2: cell.counter = 0 @@ -264,7 +276,8 @@ metainterp_sd.profiler.end_running() if vinfo is not None: vinfo.reset_vable_token(virtualizable) - loop_token = fail_descr.handle_fail(metainterp_sd) + loop_token = fail_descr.handle_fail(metainterp_sd, + jitdriver_sd) maybe_compile_and_run._dont_inline_ = True self.maybe_compile_and_run = maybe_compile_and_run @@ -277,8 +290,8 @@ if hasattr(self, 'unwrap_greenkey'): return self.unwrap_greenkey # - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def unwrap_greenkey(greenkey): greenargs = () @@ -302,20 +315,10 @@ if hasattr(self, 'jit_getter'): return self.jit_getter # - class JitCell(BaseJitCell): - # the counter can mean the following things: - # counter >= 0: not yet traced, wait till threshold is reached - # counter == -1: there is an entry bridge for this cell - # counter == -2: tracing is currently going on for this cell - counter = 0 - compiled_merge_points = None - dont_trace_here = False - entry_loop_token = None - # - if self.warmrunnerdesc.get_jitcell_at_ptr is None: - jit_getter = self._make_jitcell_getter_default(JitCell) + if self.jitdriver_sd._get_jitcell_at_ptr is None: + jit_getter = self._make_jitcell_getter_default() else: - jit_getter = self._make_jitcell_getter_custom(JitCell) + jit_getter = self._make_jitcell_getter_custom() # unwrap_greenkey = self.make_unwrap_greenkey() # @@ -327,10 +330,10 @@ # return jit_getter - def _make_jitcell_getter_default(self, JitCell): + def _make_jitcell_getter_default(self): "NOT_RPYTHON" - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def comparekey(greenargs1, greenargs2): i = 0 @@ -361,11 +364,11 @@ return cell return get_jitcell - def _make_jitcell_getter_custom(self, JitCell): + def _make_jitcell_getter_custom(self): "NOT_RPYTHON" rtyper = self.warmrunnerdesc.rtyper - get_jitcell_at_ptr = self.warmrunnerdesc.get_jitcell_at_ptr - set_jitcell_at_ptr = self.warmrunnerdesc.set_jitcell_at_ptr + get_jitcell_at_ptr = self.jitdriver_sd._get_jitcell_at_ptr + set_jitcell_at_ptr = self.jitdriver_sd._set_jitcell_at_ptr lltohlhack = {} # def get_jitcell(*greenargs): @@ -415,9 +418,10 @@ return self.set_future_values warmrunnerdesc = self.warmrunnerdesc + jitdriver_sd = self.jitdriver_sd cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.virtualizable_info - red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) + vinfo = jitdriver_sd.virtualizable_info + red_args_types = unrolling_iterable(jitdriver_sd._red_args_types) # def set_future_values(*redargs): i = 0 @@ -428,8 +432,8 @@ set_future_values_from_vinfo(*redargs) # if vinfo is not None: - i0 = len(warmrunnerdesc.red_args_types) - num_green_args = warmrunnerdesc.num_green_args + i0 = len(jitdriver_sd._red_args_types) + num_green_args = jitdriver_sd.num_green_args vable_static_fields = unrolling_iterable( zip(vinfo.static_extra_types, vinfo.static_fields)) vable_array_fields = unrolling_iterable( @@ -464,7 +468,7 @@ if hasattr(self, 'get_location_str'): return # - can_inline_ptr = self.warmrunnerdesc.can_inline_ptr + can_inline_ptr = self.jitdriver_sd._can_inline_ptr unwrap_greenkey = self.make_unwrap_greenkey() if can_inline_ptr is None: def can_inline_callable(*greenargs): @@ -497,10 +501,15 @@ self.get_assembler_token = get_assembler_token # - get_location_ptr = self.warmrunnerdesc.get_printable_location_ptr + get_location_ptr = self.jitdriver_sd._get_printable_location_ptr if get_location_ptr is None: + missing = '(no jitdriver.get_printable_location!)' + missingll = llstr(missing) def get_location_str(greenkey): - return '(no jitdriver.get_printable_location!)' + if we_are_translated(): + return missingll + else: + return missing else: rtyper = self.warmrunnerdesc.rtyper unwrap_greenkey = self.make_unwrap_greenkey() @@ -514,7 +523,7 @@ return res self.get_location_str = get_location_str # - confirm_enter_jit_ptr = self.warmrunnerdesc.confirm_enter_jit_ptr + confirm_enter_jit_ptr = self.jitdriver_sd._confirm_enter_jit_ptr if confirm_enter_jit_ptr is None: def confirm_enter_jit(*args): return True From arigo at codespeak.net Fri Jun 11 15:59:37 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 15:59:37 +0200 (CEST) Subject: [pypy-svn] r75272 - in pypy/branch: multijit multijit-2 Message-ID: <20100611135937.EDB15282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 15:59:36 2010 New Revision: 75272 Removed: pypy/branch/multijit/ pypy/branch/multijit-2/ Log: Remove old branches. From arigo at codespeak.net Fri Jun 11 16:23:39 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 16:23:39 +0200 (CEST) Subject: [pypy-svn] r75274 - pypy/branch/jit-call-assembler Message-ID: <20100611142339.1202D282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 16:23:37 2010 New Revision: 75274 Added: pypy/branch/jit-call-assembler/ - copied from r75273, pypy/trunk/ Log: A branch in which to debug r75002, r75004 and r75012. From arigo at codespeak.net Fri Jun 11 16:26:38 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 16:26:38 +0200 (CEST) Subject: [pypy-svn] r75275 - in pypy/branch/jit-call-assembler/pypy/jit: backend backend/x86 metainterp Message-ID: <20100611142638.9A16B282BEF@codespeak.net> Author: arigo Date: Fri Jun 11 16:26:36 2010 New Revision: 75275 Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/model.py pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Log: Repeat r75002, r75004 and r75012. Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/model.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/model.py Fri Jun 11 16:26:36 2010 @@ -7,7 +7,10 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py Fri Jun 11 16:26:36 2010 @@ -1364,28 +1364,72 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) - jmp_location = mc.get_relative_pos() - offset = jmp_location - je_location - assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + if op.result is not None: + mc.JMP(rel8_patched_later) # done + jmp_location = mc.get_relative_pos() + # + # Path B: load the return value directly from fail_boxes_xxx[0] + offset = jmp_location - je_location + assert 0 < offset <= 127 + mc.overwrite(je_location - 1, [chr(offset)]) + # + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + else: + # in that case, don't generate a JMP at all, + # because "Path B" is empty + jmp_location = je_location + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py Fri Jun 11 16:26:36 2010 @@ -640,7 +640,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 16:26:36 2010 @@ -1103,8 +1103,10 @@ self.__dict__.update(compile.make_done_loop_tokens()) # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) def _freeze_(self): return True From arigo at codespeak.net Fri Jun 11 16:41:38 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 16:41:38 +0200 (CEST) Subject: [pypy-svn] r75276 - pypy/branch/jit-call-assembler Message-ID: <20100611144138.D0C2A282BEF@codespeak.net> Author: arigo Date: Fri Jun 11 16:41:37 2010 New Revision: 75276 Removed: pypy/branch/jit-call-assembler/ Log: Kill it, will be redone from a version of trunk that is known to translate. From arigo at codespeak.net Fri Jun 11 16:42:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 16:42:52 +0200 (CEST) Subject: [pypy-svn] r75277 - pypy/branch/jit-call-assembler Message-ID: <20100611144252.2FBDE282BEF@codespeak.net> Author: arigo Date: Fri Jun 11 16:42:50 2010 New Revision: 75277 Added: pypy/branch/jit-call-assembler/ - copied from r75239, pypy/trunk/ Log: A branch in which to debug r75002, r75004 and r75012. From arigo at codespeak.net Fri Jun 11 16:43:39 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 16:43:39 +0200 (CEST) Subject: [pypy-svn] r75278 - in pypy/branch/jit-call-assembler/pypy/jit: backend backend/x86 metainterp Message-ID: <20100611144339.7B5F7282BEF@codespeak.net> Author: arigo Date: Fri Jun 11 16:43:37 2010 New Revision: 75278 Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/model.py pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Log: Repeat r75002, r75004 and r75012. Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/model.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/model.py Fri Jun 11 16:43:37 2010 @@ -7,7 +7,10 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py Fri Jun 11 16:43:37 2010 @@ -1364,28 +1364,72 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) - jmp_location = mc.get_relative_pos() - offset = jmp_location - je_location - assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + if op.result is not None: + mc.JMP(rel8_patched_later) # done + jmp_location = mc.get_relative_pos() + # + # Path B: load the return value directly from fail_boxes_xxx[0] + offset = jmp_location - je_location + assert 0 < offset <= 127 + mc.overwrite(je_location - 1, [chr(offset)]) + # + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + else: + # in that case, don't generate a JMP at all, + # because "Path B" is empty + jmp_location = je_location + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/x86/regalloc.py Fri Jun 11 16:43:37 2010 @@ -640,7 +640,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 16:43:37 2010 @@ -1103,8 +1103,10 @@ self.__dict__.update(compile.make_done_loop_tokens()) # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) def _freeze_(self): return True From afa at codespeak.net Fri Jun 11 17:08:09 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 11 Jun 2010 17:08:09 +0200 (CEST) Subject: [pypy-svn] r75279 - pypy/trunk/pypy/translator/platform Message-ID: <20100611150809.45D96282BEC@codespeak.net> Author: afa Date: Fri Jun 11 17:08:07 2010 New Revision: 75279 Modified: pypy/trunk/pypy/translator/platform/posix.py pypy/trunk/pypy/translator/platform/windows.py Log: Copy the "link_flags" list before we modify it: it's probably a class attribute Modified: pypy/trunk/pypy/translator/platform/posix.py ============================================================================== --- pypy/trunk/pypy/translator/platform/posix.py (original) +++ pypy/trunk/pypy/translator/platform/posix.py Fri Jun 11 17:08:07 2010 @@ -84,7 +84,7 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Fri Jun 11 17:08:07 2010 @@ -213,7 +213,7 @@ m.exe_name = exe_name m.eci = eci - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + [ '/EXPORT:$(PYPY_MAIN_FUNCTION)'] From arigo at codespeak.net Fri Jun 11 17:10:21 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 17:10:21 +0200 (CEST) Subject: [pypy-svn] r75280 - pypy/branch/jit-call-assembler/pypy/jit/metainterp Message-ID: <20100611151021.11C15282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 17:10:20 2010 New Revision: 75280 Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Log: This must be done after self.result_type is initialized. Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 17:10:20 2010 @@ -1102,11 +1102,6 @@ self._addr2name_values = [] self.__dict__.update(compile.make_done_loop_tokens()) - # store this information for fastpath of call_assembler - name = self.result_type - tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) - num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) - setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) def _freeze_(self): return True @@ -1149,6 +1144,12 @@ RESULT = codewriter.portal_graph.getreturnvar().concretetype self.result_type = history.getkind(RESULT) # + # store this information for fastpath of call_assembler + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args From fijal at codespeak.net Fri Jun 11 19:15:21 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jun 2010 19:15:21 +0200 (CEST) Subject: [pypy-svn] r75281 - pypy/build/bot2/pypybuildbot Message-ID: <20100611171521.0D70F282BEC@codespeak.net> Author: fijal Date: Fri Jun 11 19:15:20 2010 New Revision: 75281 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Be safe against already existing directories Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 11 19:15:20 2010 @@ -23,7 +23,8 @@ masterdest = properties.render(self.masterdest) masterdest = os.path.expanduser(masterdest) masterdest = os.path.join(masterdest, branch) - os.makedirs(masterdest) + if not os.path.exists(masterdest): + os.makedirs(masterdest) masterdest = os.path.join(masterdest, self.basename) self.masterdest = masterdest transfer.FileUpload.start(self) From arigo at codespeak.net Fri Jun 11 20:03:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 20:03:52 +0200 (CEST) Subject: [pypy-svn] r75282 - pypy/branch/jit-call-assembler/pypy/jit/metainterp/test Message-ID: <20100611180352.610E4282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 20:03:48 2010 New Revision: 75282 Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py Log: A failing test. Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py Fri Jun 11 20:03:48 2010 @@ -1,6 +1,7 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint -from pypy.rlib.jit import unroll_safe +from pypy.rlib.jit import unroll_safe, dont_look_inside +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr @@ -750,6 +751,59 @@ res = self.meta_interp(main, [0], inline=True) assert res == main(0) + def test_directly_call_assembler_virtualizable_reset_token(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rlib.debug import llinterpcall + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno : str(codeno), + can_inline = lambda codeno : False) + + @dont_look_inside + def check_frame(subframe): + if we_are_translated(): + llinterpcall(lltype.Void, check_ll_frame, subframe) + def check_ll_frame(ll_subframe): + # This is called with the low-level Struct that is the frame. + # Check that the vable_token was correctly reset to zero. + # Note that in order for that test to catch failures, it needs + # three levels of recursion: the vable_token of the subframe + # at the level 2 is set to a non-zero value when doing the + # call to the level 3 only. + assert ll_subframe.vable_token == 0 + + def main(codeno): + frame = Frame() + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 5: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno < 2: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(codeno + 1, subframe) + check_frame(subframe) + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + res = self.meta_interp(main, [0], inline=True) + assert res == main(0) + def test_directly_call_assembler_virtualizable_force(self): class Thing(object): def __init__(self, val): From arigo at codespeak.net Fri Jun 11 20:05:05 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 20:05:05 +0200 (CEST) Subject: [pypy-svn] r75283 - pypy/branch/jit-call-assembler/pypy/jit/metainterp/test Message-ID: <20100611180505.1B4B3282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 20:04:56 2010 New Revision: 75283 Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py Log: Ah, I forgot to mention that the test only fails in the x86 backend. Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/test/test_recursive.py Fri Jun 11 20:04:56 2010 @@ -777,7 +777,8 @@ # Note that in order for that test to catch failures, it needs # three levels of recursion: the vable_token of the subframe # at the level 2 is set to a non-zero value when doing the - # call to the level 3 only. + # call to the level 3 only. This used to fail when the test + # is run via pypy.jit.backend.x86.test.test_recursive. assert ll_subframe.vable_token == 0 def main(codeno): From arigo at codespeak.net Fri Jun 11 20:11:29 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 20:11:29 +0200 (CEST) Subject: [pypy-svn] r75284 - in pypy/branch/jit-call-assembler/pypy/jit: backend/x86 metainterp Message-ID: <20100611181129.2D4C6282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 20:11:26 2010 New Revision: 75284 Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py pypy/branch/jit-call-assembler/pypy/jit/metainterp/virtualizable.py pypy/branch/jit-call-assembler/pypy/jit/metainterp/warmspot.py Log: Fix for r75282. The CALL_ASSEMBLER operation is really really really becoming far too much of a special-case... Modified: pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/backend/x86/assembler.py Fri Jun 11 20:11:26 2010 @@ -1394,15 +1394,26 @@ if isinstance(result_loc, MODRM64): mc.FSTP(result_loc) #else: result_loc is already either eax or None, checked below + mc.JMP(rel8_patched_later) # done + jmp_location = mc.get_relative_pos() + # + # Path B: fast path. Must load the return value, and reset the token + offset = jmp_location - je_location + assert 0 < offset <= 127 + mc.overwrite(je_location - 1, [chr(offset)]) + # + # Reset the vable token --- XXX really too much special logic here:-( + if self.cpu.index_of_virtualizable >= 0: + from pypy.jit.backend.llsupport.descr import BaseFieldDescr + fielddescr = self.cpu.vable_token_descr + assert isinstance(fielddescr, BaseFieldDescr) + ofs = fielddescr.offset + mc.MOV(eax, arglocs[1]) + mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + # in the line above, TOKEN_NONE = 0 + # if op.result is not None: - mc.JMP(rel8_patched_later) # done - jmp_location = mc.get_relative_pos() - # - # Path B: load the return value directly from fail_boxes_xxx[0] - offset = jmp_location - je_location - assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) - # + # load the return value from fail_boxes_xxx[0] kind = op.result.type if kind == FLOAT: xmmtmp = X86XMMRegisterManager.all_regs[0] @@ -1420,14 +1431,10 @@ mc.XCHG(eax, heap(adr)) else: raise AssertionError(kind) - else: - # in that case, don't generate a JMP at all, - # because "Path B" is empty - jmp_location = je_location # # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location - assert 0 < offset <= 127 + assert 0 <= offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/virtualizable.py Fri Jun 11 20:11:26 2010 @@ -11,7 +11,7 @@ class VirtualizableInfo: - TOKEN_NONE = 0 + TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 def __init__(self, warmrunnerdesc): Modified: pypy/branch/jit-call-assembler/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/jit-call-assembler/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/jit-call-assembler/pypy/jit/metainterp/warmspot.py Fri Jun 11 20:11:26 2010 @@ -604,8 +604,10 @@ if vinfo is not None: self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) + self.cpu.vable_token_descr = vinfo.vable_token_descr else: self.cpu.index_of_virtualizable = -1 + self.cpu.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr From arigo at codespeak.net Fri Jun 11 20:19:21 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 20:19:21 +0200 (CEST) Subject: [pypy-svn] r75285 - pypy/branch/int-between Message-ID: <20100611181921.4F7A8282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 20:19:19 2010 New Revision: 75285 Added: pypy/branch/int-between/ - copied from r75284, pypy/trunk/ Log: A branch in which to retry having 'int_between' as a low-level operation. From arigo at codespeak.net Fri Jun 11 21:19:36 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 21:19:36 +0200 (CEST) Subject: [pypy-svn] r75286 - in pypy/branch/int-between/pypy/jit: codewriter codewriter/test metainterp/test Message-ID: <20100611191936.988EE282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 21:19:12 2010 New Revision: 75286 Modified: pypy/branch/int-between/pypy/jit/codewriter/jtransform.py pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py pypy/branch/int-between/pypy/jit/codewriter/test/test_jtransform.py pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Log: Tests and fixes. Modified: pypy/branch/int-between/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/int-between/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/int-between/pypy/jit/codewriter/jtransform.py Fri Jun 11 21:19:12 2010 @@ -140,6 +140,7 @@ if op.opname not in ('int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_is_zero', 'int_is_true', + 'uint_lt','uint_le','uint_gt','uint_ge', 'ptr_eq', 'ptr_ne', 'ptr_iszero', 'ptr_nonzero'): return False # not a supported operation @@ -190,6 +191,10 @@ 'int_le': 'int_ge', 'int_gt': 'int_lt', 'int_ge': 'int_le', + 'uint_lt': 'uint_gt', + 'uint_le': 'uint_ge', + 'uint_gt': 'uint_lt', + 'uint_ge': 'uint_le', 'float_lt': 'float_gt', 'float_le': 'float_ge', 'float_gt': 'float_lt', @@ -210,6 +215,10 @@ rewrite_op_int_le = _rewrite_symmetric rewrite_op_int_gt = _rewrite_symmetric rewrite_op_int_ge = _rewrite_symmetric + rewrite_op_uint_lt = _rewrite_symmetric + rewrite_op_uint_le = _rewrite_symmetric + rewrite_op_uint_gt = _rewrite_symmetric + rewrite_op_uint_ge = _rewrite_symmetric rewrite_op_float_add = _rewrite_symmetric rewrite_op_float_mul = _rewrite_symmetric @@ -707,16 +716,11 @@ ('uint_floordiv_zer', 'int_floordiv_zer'), ('uint_mod', 'int_mod'), ('uint_mod_zer', 'int_mod_zer'), - ('uint_lt', 'int_lt'), - ('uint_le', 'int_le'), ('uint_eq', 'int_eq'), ('uint_ne', 'int_ne'), - ('uint_gt', 'int_gt'), - ('uint_ge', 'int_ge'), ('uint_and', 'int_and'), ('uint_or', 'int_or'), ('uint_lshift', 'int_lshift'), - ('uint_rshift', 'int_rshift'), ('uint_xor', 'int_xor'), ]: assert _old not in locals() Modified: pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py Fri Jun 11 21:19:12 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import lltype, rclass, rstr from pypy.objspace.flow.model import SpaceOperation, Variable, Constant from pypy.translator.unsimplify import varoftype -from pypy.rlib.rarithmetic import ovfcheck +from pypy.rlib.rarithmetic import ovfcheck, r_uint from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver from pypy.rlib.objectmodel import keepalive_until_here from pypy.rlib import jit @@ -705,3 +705,13 @@ int_add %i1, %i2 -> %i3 int_return %i3 """, transform=True) + + def test_uint_operations(self): + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + self.encoding_test(f, [200], """ + int_sub %i0, $123L -> %i1 + uint_rshift %i1, $1L -> %i2 + uint_le %i2, $456L -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/branch/int-between/pypy/jit/codewriter/test/test_jtransform.py ============================================================================== --- pypy/branch/int-between/pypy/jit/codewriter/test/test_jtransform.py (original) +++ pypy/branch/int-between/pypy/jit/codewriter/test/test_jtransform.py Fri Jun 11 21:19:12 2010 @@ -150,7 +150,8 @@ ops = {'int_add': 'int_add', 'int_or': 'int_or', 'int_gt': ('int_gt', 'int_lt'), - 'uint_le': ('int_le', 'int_ge'), + 'uint_eq': 'int_eq', + 'uint_le': ('uint_le', 'uint_ge'), 'char_ne': 'int_ne', 'char_lt': ('int_lt', 'int_gt'), 'uint_xor': 'int_xor', Modified: pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 21:19:12 2010 @@ -538,6 +538,16 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_uint_operations(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + res = self.interp_operations(f, [50]) + assert res == False + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + def test_getfield(self): class A: pass From arigo at codespeak.net Fri Jun 11 21:32:59 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 21:32:59 +0200 (CEST) Subject: [pypy-svn] r75287 - in pypy/trunk/pypy/jit: codewriter codewriter/test metainterp/test Message-ID: <20100611193259.02F57282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 21:32:56 2010 New Revision: 75287 Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py pypy/trunk/pypy/jit/codewriter/test/test_flatten.py pypy/trunk/pypy/jit/codewriter/test/test_jtransform.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py Log: (merge from branch/int-between) The unsigned integer operations that need to be handled differently than the signed ones were not, in fact, handled differently. Oups. Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/jtransform.py (original) +++ pypy/trunk/pypy/jit/codewriter/jtransform.py Fri Jun 11 21:32:56 2010 @@ -140,6 +140,7 @@ if op.opname not in ('int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_is_zero', 'int_is_true', + 'uint_lt','uint_le','uint_gt','uint_ge', 'ptr_eq', 'ptr_ne', 'ptr_iszero', 'ptr_nonzero'): return False # not a supported operation @@ -190,6 +191,10 @@ 'int_le': 'int_ge', 'int_gt': 'int_lt', 'int_ge': 'int_le', + 'uint_lt': 'uint_gt', + 'uint_le': 'uint_ge', + 'uint_gt': 'uint_lt', + 'uint_ge': 'uint_le', 'float_lt': 'float_gt', 'float_le': 'float_ge', 'float_gt': 'float_lt', @@ -210,6 +215,10 @@ rewrite_op_int_le = _rewrite_symmetric rewrite_op_int_gt = _rewrite_symmetric rewrite_op_int_ge = _rewrite_symmetric + rewrite_op_uint_lt = _rewrite_symmetric + rewrite_op_uint_le = _rewrite_symmetric + rewrite_op_uint_gt = _rewrite_symmetric + rewrite_op_uint_ge = _rewrite_symmetric rewrite_op_float_add = _rewrite_symmetric rewrite_op_float_mul = _rewrite_symmetric @@ -707,16 +716,11 @@ ('uint_floordiv_zer', 'int_floordiv_zer'), ('uint_mod', 'int_mod'), ('uint_mod_zer', 'int_mod_zer'), - ('uint_lt', 'int_lt'), - ('uint_le', 'int_le'), ('uint_eq', 'int_eq'), ('uint_ne', 'int_ne'), - ('uint_gt', 'int_gt'), - ('uint_ge', 'int_ge'), ('uint_and', 'int_and'), ('uint_or', 'int_or'), ('uint_lshift', 'int_lshift'), - ('uint_rshift', 'int_rshift'), ('uint_xor', 'int_xor'), ]: assert _old not in locals() Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Fri Jun 11 21:32:56 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import lltype, rclass, rstr from pypy.objspace.flow.model import SpaceOperation, Variable, Constant from pypy.translator.unsimplify import varoftype -from pypy.rlib.rarithmetic import ovfcheck +from pypy.rlib.rarithmetic import ovfcheck, r_uint from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver from pypy.rlib.objectmodel import keepalive_until_here from pypy.rlib import jit @@ -705,3 +705,13 @@ int_add %i1, %i2 -> %i3 int_return %i3 """, transform=True) + + def test_uint_operations(self): + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + self.encoding_test(f, [200], """ + int_sub %i0, $123L -> %i1 + uint_rshift %i1, $1L -> %i2 + uint_le %i2, $456L -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/trunk/pypy/jit/codewriter/test/test_jtransform.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_jtransform.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_jtransform.py Fri Jun 11 21:32:56 2010 @@ -150,7 +150,8 @@ ops = {'int_add': 'int_add', 'int_or': 'int_or', 'int_gt': ('int_gt', 'int_lt'), - 'uint_le': ('int_le', 'int_ge'), + 'uint_eq': 'int_eq', + 'uint_le': ('uint_le', 'uint_ge'), 'char_ne': 'int_ne', 'char_lt': ('int_lt', 'int_gt'), 'uint_xor': 'int_xor', Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 21:32:56 2010 @@ -538,6 +538,16 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_uint_operations(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + res = self.interp_operations(f, [50]) + assert res == False + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + def test_getfield(self): class A: pass From arigo at codespeak.net Fri Jun 11 21:39:33 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 21:39:33 +0200 (CEST) Subject: [pypy-svn] r75288 - in pypy/trunk/pypy/jit: codewriter metainterp/test Message-ID: <20100611193933.D7EE0282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 21:39:32 2010 New Revision: 75288 Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py Log: Baaaah. Two more operations should not be converted, and two operation (uint_xxx_zer) probably don't need to be implemented at all so far. Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/jtransform.py (original) +++ pypy/trunk/pypy/jit/codewriter/jtransform.py Fri Jun 11 21:39:32 2010 @@ -712,10 +712,6 @@ ('uint_add', 'int_add'), ('uint_sub', 'int_sub'), ('uint_mul', 'int_mul'), - ('uint_floordiv', 'int_floordiv'), - ('uint_floordiv_zer', 'int_floordiv_zer'), - ('uint_mod', 'int_mod'), - ('uint_mod_zer', 'int_mod_zer'), ('uint_eq', 'int_eq'), ('uint_ne', 'int_ne'), ('uint_and', 'int_and'), Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 21:39:32 2010 @@ -233,8 +233,8 @@ b = r_uint(b) return a/b - res = self.interp_operations(f, [4, 3]) - assert res == 1 + res = self.interp_operations(f, [-4, 3]) + assert res == long(r_uint(-4)) // 3 def test_direct_call(self): def g(n): From arigo at codespeak.net Fri Jun 11 21:44:19 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 21:44:19 +0200 (CEST) Subject: [pypy-svn] r75289 - in pypy/trunk/pypy/jit: backend backend/x86 metainterp metainterp/test Message-ID: <20100611194419.47C5A282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 21:44:17 2010 New Revision: 75289 Modified: pypy/trunk/pypy/jit/backend/model.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/test/test_recursive.py pypy/trunk/pypy/jit/metainterp/virtualizable.py pypy/trunk/pypy/jit/metainterp/warmspot.py Log: Merge branch/jit-call-assembler: finish the handling of the fast path in CALL_ASSEMBLER. Also tests and fixes a bug: in the fast path, we have to clear the vable_token of the virtualizable. Modified: pypy/trunk/pypy/jit/backend/model.py ============================================================================== --- pypy/trunk/pypy/jit/backend/model.py (original) +++ pypy/trunk/pypy/jit/backend/model.py Fri Jun 11 21:44:17 2010 @@ -7,7 +7,10 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Fri Jun 11 21:44:17 2010 @@ -1364,28 +1364,79 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + mc.JMP(rel8_patched_later) # done jmp_location = mc.get_relative_pos() + # + # Path B: fast path. Must load the return value, and reset the token offset = jmp_location - je_location assert 0 < offset <= 127 mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + # + # Reset the vable token --- XXX really too much special logic here:-( + if self.cpu.index_of_virtualizable >= 0: + from pypy.jit.backend.llsupport.descr import BaseFieldDescr + fielddescr = self.cpu.vable_token_descr + assert isinstance(fielddescr, BaseFieldDescr) + ofs = fielddescr.offset + mc.MOV(eax, arglocs[1]) + mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + # in the line above, TOKEN_NONE = 0 + # + if op.result is not None: + # load the return value from fail_boxes_xxx[0] + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location - assert 0 < offset <= 127 + assert 0 <= offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Fri Jun 11 21:44:17 2010 @@ -640,7 +640,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 21:44:17 2010 @@ -1102,9 +1102,6 @@ self._addr2name_values = [] self.__dict__.update(compile.make_done_loop_tokens()) - # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) def _freeze_(self): return True @@ -1147,6 +1144,12 @@ RESULT = codewriter.portal_graph.getreturnvar().concretetype self.result_type = history.getkind(RESULT) # + # store this information for fastpath of call_assembler + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args Modified: pypy/trunk/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_recursive.py Fri Jun 11 21:44:17 2010 @@ -1,6 +1,7 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint -from pypy.rlib.jit import unroll_safe +from pypy.rlib.jit import unroll_safe, dont_look_inside +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr @@ -750,6 +751,60 @@ res = self.meta_interp(main, [0], inline=True) assert res == main(0) + def test_directly_call_assembler_virtualizable_reset_token(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rlib.debug import llinterpcall + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno : str(codeno), + can_inline = lambda codeno : False) + + @dont_look_inside + def check_frame(subframe): + if we_are_translated(): + llinterpcall(lltype.Void, check_ll_frame, subframe) + def check_ll_frame(ll_subframe): + # This is called with the low-level Struct that is the frame. + # Check that the vable_token was correctly reset to zero. + # Note that in order for that test to catch failures, it needs + # three levels of recursion: the vable_token of the subframe + # at the level 2 is set to a non-zero value when doing the + # call to the level 3 only. This used to fail when the test + # is run via pypy.jit.backend.x86.test.test_recursive. + assert ll_subframe.vable_token == 0 + + def main(codeno): + frame = Frame() + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 5: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno < 2: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(codeno + 1, subframe) + check_frame(subframe) + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + res = self.meta_interp(main, [0], inline=True) + assert res == main(0) + def test_directly_call_assembler_virtualizable_force(self): class Thing(object): def __init__(self, val): Modified: pypy/trunk/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/trunk/pypy/jit/metainterp/virtualizable.py Fri Jun 11 21:44:17 2010 @@ -11,7 +11,7 @@ class VirtualizableInfo: - TOKEN_NONE = 0 + TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 def __init__(self, warmrunnerdesc): Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Fri Jun 11 21:44:17 2010 @@ -604,8 +604,10 @@ if vinfo is not None: self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) + self.cpu.vable_token_descr = vinfo.vable_token_descr else: self.cpu.index_of_virtualizable = -1 + self.cpu.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr From arigo at codespeak.net Fri Jun 11 21:44:31 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 21:44:31 +0200 (CEST) Subject: [pypy-svn] r75290 - pypy/branch/jit-call-assembler Message-ID: <20100611194431.A1715282BEF@codespeak.net> Author: arigo Date: Fri Jun 11 21:44:29 2010 New Revision: 75290 Removed: pypy/branch/jit-call-assembler/ Log: Remove merged branch. From arigo at codespeak.net Fri Jun 11 22:04:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 22:04:52 +0200 (CEST) Subject: [pypy-svn] r75291 - in pypy/branch/int-between/pypy: rpython/lltypesystem translator/c/src Message-ID: <20100611200452.2AF8F282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 22:04:50 2010 New Revision: 75291 Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py pypy/branch/int-between/pypy/rpython/lltypesystem/rclass.py pypy/branch/int-between/pypy/translator/c/src/int.h Log: Add the lloperation 'int_between'. Use it only in rclass for now. Implement it in the C backend. Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py Fri Jun 11 22:04:50 2010 @@ -227,6 +227,8 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), + 'int_between': LLOp(canfold=True), # a <= b <= c + 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), # ^^^ more efficient version when 2nd arg is nonneg Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py Fri Jun 11 22:04:50 2010 @@ -197,6 +197,12 @@ assert isinstance(y, int) return intmask(x - y) +def op_int_between(a, b, c): + assert lltype.typeOf(a) is lltype.Signed + assert lltype.typeOf(b) is lltype.Signed + assert lltype.typeOf(c) is lltype.Signed + return a <= b <= c + def op_int_and(x, y): if not isinstance(x, int): from pypy.rpython.lltypesystem import llgroup Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/int-between/pypy/rpython/lltypesystem/rclass.py Fri Jun 11 22:04:50 2010 @@ -22,6 +22,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel from pypy.lib.identity_dict import identity_dict +from pypy.rpython.lltypesystem.lloperation import llop # # There is one "vtable" per user class, with the following structure: @@ -645,10 +646,12 @@ return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): - return cls.subclassrange_min <= subcls.subclassrange_min <= cls.subclassrange_max + return llop.int_between(Bool, cls.subclassrange_min, + subcls.subclassrange_min, + cls.subclassrange_max) def ll_issubclass_const(subcls, minid, maxid): - return minid <= subcls.subclassrange_min <= maxid + return llop.int_between(Bool, minid, subcls.subclassrange_min, maxid) def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT Modified: pypy/branch/int-between/pypy/translator/c/src/int.h ============================================================================== --- pypy/branch/int-between/pypy/translator/c/src/int.h (original) +++ pypy/branch/int-between/pypy/translator/c/src/int.h Fri Jun 11 22:04:50 2010 @@ -47,6 +47,14 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) +/* Implement INT_BETWEEN by optimizing for the common case where a and c + are constants (the 2nd subtraction below is then constant-folded), or + for the case of a == 0 (both subtractions are then constant-folded). + Note that the following line only works if a <= c in the first place, + which we assume is true. */ +#define OP_INT_BETWEEN(a,b,c,r) r = (((unsigned long)b - (unsigned long)a) \ + <= ((unsigned long)c - (unsigned long)a)) + /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) From arigo at codespeak.net Fri Jun 11 22:41:46 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 22:41:46 +0200 (CEST) Subject: [pypy-svn] r75292 - in pypy/branch/int-between/pypy/jit: codewriter/test metainterp metainterp/test Message-ID: <20100611204146.D26C9282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 22:41:45 2010 New Revision: 75292 Modified: pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py pypy/branch/int-between/pypy/jit/metainterp/blackhole.py pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Log: Implement int_between in the jit. Modified: pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/int-between/pypy/jit/codewriter/test/test_flatten.py Fri Jun 11 22:41:45 2010 @@ -715,3 +715,12 @@ uint_le %i2, $456L -> %i3 int_return %i3 """, transform=True) + + def test_int_between(self): + from pypy.rpython.lltypesystem.lloperation import llop + def f(n, m, p): + return llop.int_between(lltype.Bool, n, m, p) + self.encoding_test(f, [5, 6, 7], """ + int_between %i0, %i1, %i2 -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/branch/int-between/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/blackhole.py Fri Jun 11 22:41:45 2010 @@ -475,6 +475,9 @@ @arguments("i", returns="i") def bhimpl_int_is_true(a): return bool(a) + @arguments("i", "i", "i", returns="i") + def bhimpl_int_between(a, b, c): + return a <= b <= c @arguments("i", "i", returns="i") def bhimpl_uint_lt(a, b): Modified: pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py Fri Jun 11 22:41:45 2010 @@ -315,6 +315,12 @@ if value: self.pc = target + @arguments("box", "box", "box") + def opimpl_int_between(self, b1, b2, b3): + b4 = self.execute(rop.INT_SUB, b2, b1) + b5 = self.execute(rop.INT_SUB, b3, b1) + return self.execute(rop.UINT_LE, b4, b5) + @arguments("box", "descr", "orgpc") def opimpl_switch(self, valuebox, switchdict, orgpc): box = self.implement_guard_value(orgpc, valuebox) Modified: pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 22:41:45 2010 @@ -145,6 +145,9 @@ def check_operations_history(self, expected=None, **isns): # this can be used after interp_operations + if expected is not None: + expected = dict(expected) + expected['jump'] = 1 self.metainterp.staticdata.stats.check_history(expected, **isns) @@ -548,6 +551,51 @@ int_le=0, uint_le=1, int_sub=1) + def test_int_between(self): + # + def check(arg1, arg2, arg3, expect_result, **expect_operations): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop + loc = locals().copy() + exec py.code.Source(""" + def f(n, m, p): + arg1 = %(arg1)s + arg2 = %(arg2)s + arg3 = %(arg3)s + return llop.int_between(lltype.Bool, arg1, arg2, arg3) + """ % locals()).compile() in loc + res = self.interp_operations(loc['f'], [5, 6, 7]) + assert res == expect_result + self.check_operations_history(expect_operations) + # + check('n', 'm', 'p', True, int_sub=2, uint_le=1) + check('n', 'p', 'm', False, int_sub=2, uint_le=1) + # + check('n', 'm', 6, True, int_sub=2, uint_le=1) + # + check('n', 4, 'p', False, int_sub=2, uint_le=1) + check('n', 5, 'p', True, int_sub=2, uint_le=1) + check('n', 8, 'p', False, int_sub=2, uint_le=1) + # + check('n', 6, 7, True, int_sub=2, uint_le=1) + # + check(-2, 'n', 'p', True, int_sub=2, uint_le=1) + check(-2, 'm', 'p', True, int_sub=2, uint_le=1) + check(-2, 'p', 'm', False, int_sub=2, uint_le=1) + #check(0, 'n', 'p', True, uint_le=1) xxx implement me + #check(0, 'm', 'p', True, uint_le=1) + #check(0, 'p', 'm', False, uint_le=1) + # + check(2, 'n', 6, True, int_sub=1, uint_le=1) + check(2, 'm', 6, True, int_sub=1, uint_le=1) + check(2, 'p', 6, False, int_sub=1, uint_le=1) + # + check(2, 6, 'n', False, int_sub=1, uint_le=1) + check(2, 6, 'm', True, int_sub=1, uint_le=1) + # + check(2, 40, 6, False) + check(2, 40, 60, True) + def test_getfield(self): class A: pass From arigo at codespeak.net Fri Jun 11 22:46:35 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 22:46:35 +0200 (CEST) Subject: [pypy-svn] r75293 - in pypy/trunk/pypy/jit: codewriter metainterp/test Message-ID: <20100611204635.649BC282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 22:46:33 2010 New Revision: 75293 Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py Log: Test and fix (for now by not having goto_if_not_uint_xx comparison operators, but only uint_xx). Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/jtransform.py (original) +++ pypy/trunk/pypy/jit/codewriter/jtransform.py Fri Jun 11 22:46:33 2010 @@ -140,7 +140,6 @@ if op.opname not in ('int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_is_zero', 'int_is_true', - 'uint_lt','uint_le','uint_gt','uint_ge', 'ptr_eq', 'ptr_ne', 'ptr_iszero', 'ptr_nonzero'): return False # not a supported operation Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 22:46:33 2010 @@ -548,6 +548,19 @@ int_le=0, uint_le=1, int_sub=1) + def test_uint_condition(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + if ((r_uint(n) - 123) >> 1) <= r_uint(456): + return 24 + else: + return 12 + res = self.interp_operations(f, [50]) + assert res == 12 + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + def test_getfield(self): class A: pass From arigo at codespeak.net Fri Jun 11 23:04:01 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 23:04:01 +0200 (CEST) Subject: [pypy-svn] r75294 - in pypy/branch/int-between/pypy/jit: codewriter metainterp/test Message-ID: <20100611210401.9E431282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 23:04:00 2010 New Revision: 75294 Modified: pypy/branch/int-between/pypy/jit/codewriter/jtransform.py pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Log: Merge r75293 from trunk. Modified: pypy/branch/int-between/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/int-between/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/int-between/pypy/jit/codewriter/jtransform.py Fri Jun 11 23:04:00 2010 @@ -140,7 +140,6 @@ if op.opname not in ('int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_is_zero', 'int_is_true', - 'uint_lt','uint_le','uint_gt','uint_ge', 'ptr_eq', 'ptr_ne', 'ptr_iszero', 'ptr_nonzero'): return False # not a supported operation Modified: pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Fri Jun 11 23:04:00 2010 @@ -551,6 +551,19 @@ int_le=0, uint_le=1, int_sub=1) + def test_uint_condition(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + if ((r_uint(n) - 123) >> 1) <= r_uint(456): + return 24 + else: + return 12 + res = self.interp_operations(f, [50]) + assert res == 12 + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + def test_int_between(self): # def check(arg1, arg2, arg3, expect_result, **expect_operations): From arigo at codespeak.net Fri Jun 11 23:04:22 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jun 2010 23:04:22 +0200 (CEST) Subject: [pypy-svn] r75295 - pypy/branch/int-between/pypy/rpython Message-ID: <20100611210422.E9A18282BEC@codespeak.net> Author: arigo Date: Fri Jun 11 23:04:21 2010 New Revision: 75295 Modified: pypy/branch/int-between/pypy/rpython/normalizecalls.py Log: Add support for subtraction between TotalOrderSymbolic. Modified: pypy/branch/int-between/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/normalizecalls.py (original) +++ pypy/branch/int-between/pypy/rpython/normalizecalls.py Fri Jun 11 23:04:21 2010 @@ -292,6 +292,13 @@ else: return cmp(self.orderwitness, other.orderwitness) + # support for implementing int_between: (a<=b<=c) with (b-a<=c-a) + # see pypy.jit.metainterp.pyjitpl.opimpl_int_between + def __sub__(self, other): + return self.compute_fn() - other + def __rsub__(self, other): + return other - self.compute_fn() + def compute_fn(self): if self.value is None: self.peers.sort() From jcreigh at codespeak.net Sat Jun 12 00:19:25 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Sat, 12 Jun 2010 00:19:25 +0200 (CEST) Subject: [pypy-svn] r75296 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend: test x86 x86/test x86/tool Message-ID: <20100611221925.88AF6282BEC@codespeak.net> Author: jcreigh Date: Sat Jun 12 00:19:21 2010 New Revision: 75296 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zll_random.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/tool/viewcode.py Log: first shot at real 64-bit support (doesn't translate, pretty ugly in places, some stuff is still broken) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py Sat Jun 12 00:19:21 2010 @@ -465,6 +465,25 @@ [funcbox] + args, 'float', descr=calldescr) assert abs(res.value - 4.6) < 0.0001 + + def test_call_many_arguments(self): + # Test calling a function with a large number of arguments (more than + # 6, which will force passing some arguments on the stack on 64-bit) + + def func(*args): + assert len(args) == 16 + # Try to sum up args in a way that would probably detect a + # transposed argument + return sum(arg * (2**i) for i, arg in enumerate(args)) + + FUNC = self.FuncType([lltype.Signed]*16, lltype.Signed) + FPTR = self.Ptr(FUNC) + calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) + func_ptr = llhelper(FPTR, func) + args = range(16) + funcbox = self.get_funcbox(self.cpu, func_ptr) + res = self.execute_operation(rop.CALL, [funcbox] + map(BoxInt, args), 'int', descr=calldescr) + assert res.value == func(*args) def test_call_stack_alignment(self): # test stack alignment issues, notably for Mac OS/X. Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Sat Jun 12 00:19:21 2010 @@ -15,6 +15,10 @@ esp, ebp, esi, edi, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + r8, r9, r10, r11, + r12, r13, r14, r15, + X86_64_SCRATCH_REG, + X86_64_XMM_SCRATCH_REG, RegLoc, StackLoc, ImmedLoc, AddressLoc, imm, rel32) @@ -30,7 +34,7 @@ # darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0, # better safe than sorry -CALL_ALIGN = 4 +CALL_ALIGN = 16 // WORD def align_stack_words(words): return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1) @@ -178,6 +182,7 @@ self._build_malloc_fixedsize_slowpath() def _build_float_constants(self): + """ # 11 words: 8 words for the data, and up to 3 words for alignment addr = lltype.malloc(rffi.CArray(lltype.Signed), 11, flavor='raw') if not we_are_translated(): @@ -195,23 +200,45 @@ addr[7] = 0 # self.float_const_neg_addr = float_constants self.float_const_abs_addr = float_constants + 16 + """ + + # 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment + addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw') + if not we_are_translated(): + self._keepalive_malloced_float_consts = addr + float_constants = rffi.cast(lltype.Signed, addr) + float_constants = (float_constants + 15) & ~15 # align to 16 bytes + addr = rffi.cast(rffi.CArrayPtr(lltype.Char), float_constants) + qword_padding = '\x00\x00\x00\x00\x00\x00\x00\x00' + neg_const = '\x00\x00\x00\x00\x00\x00\x00\x80' + abs_const = '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F' + data = neg_const + qword_padding + abs_const + qword_padding + for i, char in enumerate(data): + addr[i] = char + self.float_const_neg_addr = float_constants + self.float_const_abs_addr = float_constants + 16 def _build_malloc_fixedsize_slowpath(self): mc = self.mc2._mc # ---------- first helper for the slow path of malloc ---------- self.malloc_fixedsize_slowpath1 = mc.tell() if self.cpu.supports_floats: # save the XMM registers in - for i in range(8): # the *caller* frame, from esp+8 - mc.MOVSD_sx(8+8*i, i) + for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8 + mc.MOVSD_sx((WORD*2)+8*i, i) mc.SUB(edx, eax) # compute the size we want - mc.MOV_sr(4, edx.value) # save it as the new argument + if WORD == 4: + mc.MOV_sr(WORD, edx.value) # save it as the new argument + elif WORD == 8: + # FIXME: We can't just clobber rdi like this, can we? + mc.MOV_rr(edi.value, edx.value) + addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr() mc.JMP_l(addr) # tail call to the real malloc # ---------- second helper for the slow path of malloc ---------- self.malloc_fixedsize_slowpath2 = mc.tell() if self.cpu.supports_floats: # restore the XMM registers - for i in range(8): # from where they were saved - mc.MOVSD_xs(i, 8+8*i) + for i in range(self.cpu.NUM_REGS):# from where they were saved + mc.MOVSD_xs(i, (WORD*2)+8*i) nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX mc.RET() @@ -337,7 +364,7 @@ # Compute the correct offset for the instruction LEA ESP, [EBP-4*words]. # Given that [EBP] is where we saved EBP, i.e. in the last word # of our fixed frame, then the 'words' value is: - words = (FRAME_FIXED_SIZE - 1) + reserved_depth + words = (self.cpu.FRAME_FIXED_SIZE - 1) + reserved_depth # align, e.g. for Mac OS X aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP mc.writeimm32(-WORD * aligned_words) @@ -346,14 +373,25 @@ def _call_header(self): self.mc.PUSH(ebp) self.mc.MOV_rr(ebp.value, esp.value) - self.mc.PUSH(ebx) - self.mc.PUSH(esi) - self.mc.PUSH(edi) + for regloc in self.cpu.CALLEE_SAVE_REGISTERS: + self.mc.PUSH(regloc) + # NB. the shape of the frame is hard-coded in get_basic_shape() too. # Also, make sure this is consistent with FRAME_FIXED_SIZE. return self._patchable_stackadjust() + def _call_footer(self, mc): + mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD) + + for regloc in reversed(self.cpu.CALLEE_SAVE_REGISTERS): + mc.POP(regloc) + + mc.POP(ebp) + mc.RET() + def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth): + if WORD == 8: + return self._assemble_bootstrap_direct_call_64(arglocs, jmpadr, stackdepth) # XXX pushing ebx esi and edi is a bit pointless, since we store # all regsiters anyway, for the case of guard_not_forced # XXX this can be improved greatly. Right now it'll behave like @@ -386,6 +424,34 @@ self.mc.JMP_l(jmpadr) return adr_stackadjust + def _assemble_bootstrap_direct_call_64(self, arglocs, jmpadr, stackdepth): + # In reverse order for use with pop() + unused_gpr = [r9, r8, ecx, edx, esi, edi] + unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0] + + nonfloatlocs, floatlocs = arglocs + adr_stackadjust = self._call_header() + self._patch_stackadjust(adr_stackadjust, stackdepth) + + for i, loc in enumerate(nonfloatlocs): + if loc != None: + if len(unused_gpr) > 0: + self.mc.MOV(loc, unused_gpr.pop()) + else: + self.mc.MOV_rb(X86_64_SCRATCH_REG.value, (2 + i) * WORD) + self.mc.MOV(loc, X86_64_SCRATCH_REG) + + for i, loc in enumerate(floatlocs): + if loc != None: + if len(unused_xmm) > 0: + self.mc.MOVSD(loc, unused_xmm.pop()) + + self.mc.JMP_l(jmpadr) + + return adr_stackadjust + + + def _assemble_bootstrap_code(self, inputargs, arglocs): nonfloatlocs, floatlocs = arglocs adr_stackadjust = self._call_header() @@ -404,10 +470,10 @@ # reading them self.mc.XOR(target, target) adr = self.fail_boxes_ptr.get_addr_for_num(i) - self.mc.XCHG_rj(target.value, adr) + self.mc.XCHG(target, heap(adr)) else: adr = self.fail_boxes_int.get_addr_for_num(i) - self.mc.MOV_rj(target.value, adr) + self.mc.MOV(target, heap(adr)) if target is not loc: assert isinstance(loc, StackLoc) self.mc.MOV_br(loc.value, target.value) @@ -417,9 +483,9 @@ continue adr = self.fail_boxes_float.get_addr_for_num(i) if isinstance(loc, RegLoc): - self.mc.MOVSD_xj(loc.value, adr) + self.mc.MOVSD(loc, heap(adr)) else: - self.mc.MOVSD_xj(xmmtmp.value, adr) + self.mc.MOVSD(xmmtmp, heap(adr)) assert isinstance(loc, StackLoc) self.mc.MOVSD_bx(loc.value, xmmtmp.value) return adr_stackadjust @@ -540,16 +606,20 @@ def _cmpop_float(cond, is_ne=False): def genop_cmp(self, op, arglocs, result_loc): self.mc.UCOMISD(arglocs[0], arglocs[1]) - rl = result_loc.lowest8bits() - rh = result_loc.higher8bits() - self.mc.SET_ir(rx86.Conditions[cond], rl.value) + tmp1 = result_loc.lowest8bits() + if WORD == 4: + tmp2 = result_loc.higher8bits() + elif WORD == 8: + tmp2 = X86_64_SCRATCH_REG.lowest8bits() + + self.mc.SET_ir(rx86.Conditions[cond], tmp1.value) if is_ne: - self.mc.SET_ir(rx86.Conditions['P'], rh.value) - self.mc.OR8_rr(rl.value, rh.value) + self.mc.SET_ir(rx86.Conditions['P'], tmp2.value) + self.mc.OR8_rr(tmp1.value, tmp2.value) else: - self.mc.SET_ir(rx86.Conditions['NP'], rh.value) - self.mc.AND8_rr(rl.value, rh.value) - self.mc.MOVZX8_rr(result_loc.value, rl.value) + self.mc.SET_ir(rx86.Conditions['NP'], tmp2.value) + self.mc.AND8_rr(tmp1.value, tmp2.value) + self.mc.MOVZX8_rr(result_loc.value, tmp1.value) return genop_cmp def _cmpop_guard(cond, rev_cond, false_cond, false_rev_cond): @@ -592,6 +662,9 @@ @specialize.arg(5) def _emit_call(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): + if WORD == 8: + return self._emit_call_64(x, arglocs, start, tmp, force_mc, mc) + if not force_mc: mc = self.mc p = 0 @@ -619,7 +692,88 @@ # x is a location mc.CALL(x) self.mark_gc_roots() + + def _emit_call_64(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): + if not force_mc: + mc = self.mc + + # In reverse order for use with pop() + unused_gpr = [r9, r8, ecx, edx, esi, edi] + unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0] + pass_in_reg = {} + pass_on_stack = [] + + for i in range(start, len(arglocs)): + loc = arglocs[i] + assert isinstance(loc, RegLoc) or isinstance(loc, ImmedLoc) or isinstance(loc, StackLoc) + + # XXX: Should be much simplier to tell whether a location is a float! + if (isinstance(loc, RegLoc) and loc.is_xmm) or (isinstance(loc, StackLoc) and loc.type == FLOAT): + if len(unused_xmm) > 0: + pass_in_reg[unused_xmm.pop()] = loc + else: + pass_on_stack.append(loc) + else: + if len(unused_gpr) > 0: + pass_in_reg[unused_gpr.pop()] = loc + else: + pass_on_stack.append(loc) + # Emit instructions to pass the stack arguments + for i, loc in enumerate(pass_on_stack): + if isinstance(loc, StackLoc): + if loc.type == FLOAT: + mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) + mc.MOVSD_sx(i*WORD, X86_64_XMM_SCRATCH_REG.value) + else: + mc.MOV(X86_64_SCRATCH_REG, loc) + mc.MOV_sr(i*WORD, X86_64_SCRATCH_REG.value) + else: + assert isinstance(loc, RegLoc) + if loc.is_xmm: + mc.MOVSD_sx(i*WORD, loc.value) + else: + mc.MOV_sr(i*WORD, loc.value) + + previous_len = sys.maxint # dummy value to start loop + while 0 < len(pass_in_reg) < previous_len: + previous_len = len(pass_in_reg) + # XXX: Maybe a little slow to call items() and values() so much? + for reg, loc in pass_in_reg.items(): + if reg == loc: + # Happy coincidence, do nothing + del pass_in_reg[reg] + elif reg not in pass_in_reg.values(): + if reg.is_xmm: + mc.MOVSD(reg, loc) + else: + mc.MOV(reg, loc) + + del pass_in_reg[reg] + + if len(pass_in_reg) > 0: + # Rats. There is a "cycle". eg, r9 contains the value that we want + # to pass in r8, but r8 contains the value we want to pass in r9, + # so we can't just clobber r8. + # + # There's probably some clever way we could handle this, but we + # just temporarily dump the registers to the stack and then copy + # back to the correct registers. Hopefully this doesn't happen too + # often anyway. + # + # FIXME: Use of PUSH/POP will fail with XMM registers + items = pass_in_reg.items() + for reg, loc in items: + mc.PUSH(loc) + + for reg, loc in reversed(items): + mc.POP(reg) + + self._regalloc.reserve_param(len(pass_on_stack)) + mc.CALL(x) + + self.mark_gc_roots() + def call(self, addr, args, res): self._emit_call(rel32(addr), args) assert res is eax @@ -696,11 +850,11 @@ def genop_float_neg(self, op, arglocs, resloc): # Following what gcc does: res = x ^ 0x8000000000000000 - self.mc.XORPD_xj(arglocs[0].value, self.float_const_neg_addr) + self.mc.XORPD(arglocs[0], heap(self.float_const_neg_addr)) def genop_float_abs(self, op, arglocs, resloc): # Following what gcc does: res = x & 0x7FFFFFFFFFFFFFFF - self.mc.ANDPD_xj(arglocs[0].value, self.float_const_abs_addr) + self.mc.ANDPD(arglocs[0], heap(self.float_const_abs_addr)) def genop_guard_float_is_true(self, op, guard_op, addr, arglocs, resloc): guard_opnum = guard_op.opnum @@ -758,7 +912,13 @@ genop_virtual_ref = genop_same_as def genop_int_mod(self, op, arglocs, resloc): - self.mc.CDQ() + if WORD == 4: + self.mc.CDQ() + elif WORD == 8: + self.mc.CQO() + else: + raise AssertionError("Can't happen") + self.mc.IDIV_r(ecx.value) genop_int_floordiv = genop_int_mod @@ -807,14 +967,14 @@ size = size_loc.value source_addr = AddressLoc(base_loc, ofs_loc) - if size == 1: + if resloc.is_xmm: + self.mc.MOVSD(resloc, source_addr) + elif size == 1: self.mc.MOVZX8(resloc, source_addr) elif size == 2: self.mc.MOVZX16(resloc, source_addr) elif size == WORD: self.mc.MOV(resloc, source_addr) - elif size == 8: - self.mc.MOVSD(resloc, source_addr) else: raise NotImplementedError("getfield size = %d" % size) @@ -833,7 +993,7 @@ if scale.value == 0: self.mc.MOVZX8(resloc, addr8_add(base_loc, ofs_loc, ofs.value, scale.value)) - elif scale.value == 2: + elif (1 << scale.value) == WORD: self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) else: @@ -847,7 +1007,7 @@ assert isinstance(size_loc, ImmedLoc) size = size_loc.value dest_addr = AddressLoc(base_loc, ofs_loc) - if size == WORD * 2: + if isinstance(value_loc, RegLoc) and value_loc.is_xmm: self.mc.MOVSD(dest_addr, value_loc) elif size == WORD: self.mc.MOV(dest_addr, value_loc) @@ -867,7 +1027,7 @@ if op.args[2].type == FLOAT: self.mc.MOVSD(dest_addr, value_loc) else: - if scale_loc.value == 2: + if (1 << scale_loc.value) == WORD: self.mc.MOV(dest_addr, value_loc) elif scale_loc.value == 0: self.mc.MOV8(dest_addr, value_loc.lowest8bits()) @@ -887,7 +1047,7 @@ basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: - self.mc.MOV(AddressLoc(base_loc, ofs_loc, 2, basesize), val_loc) + self.mc.MOV32(AddressLoc(base_loc, ofs_loc, 2, basesize), val_loc) elif itemsize == 2: self.mc.MOV16(AddressLoc(base_loc, ofs_loc, 1, basesize), val_loc) else: @@ -925,7 +1085,7 @@ basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: - self.mc.MOV(resloc, AddressLoc(base_loc, ofs_loc, 2, basesize)) + self.mc.MOV32(resloc, AddressLoc(base_loc, ofs_loc, 2, basesize)) elif itemsize == 2: self.mc.MOVZX16(resloc, AddressLoc(base_loc, ofs_loc, 1, basesize)) else: @@ -939,7 +1099,7 @@ def genop_guard_guard_no_exception(self, ign_1, guard_op, addr, locs, ign_2): - self.mc.CMP_ji(self.cpu.pos_exception(), 0) + self.mc.CMP(heap(self.cpu.pos_exception()), imm(0)) return self.implement_guard(addr, 'NZ') def genop_guard_guard_exception(self, ign_1, guard_op, addr, @@ -1078,7 +1238,8 @@ DESCR_INT = 0x01 DESCR_FLOAT = 0x02 DESCR_SPECIAL = 0x03 - CODE_FROMSTACK = 4*8 + # XXX: 4*8 works on i386, should we optimize for that case? + CODE_FROMSTACK = 4*16 CODE_STOP = 0 | DESCR_SPECIAL CODE_HOLE = 4 | DESCR_SPECIAL @@ -1218,7 +1379,7 @@ code = (code - self.CODE_FROMSTACK) >> 2 stackloc = frame_addr + get_ebp_ofs(code) value = rffi.cast(rffi.LONGP, stackloc)[0] - if kind == self.DESCR_FLOAT: + if kind == self.DESCR_FLOAT and WORD == 4: value_hi = value value = rffi.cast(rffi.LONGP, stackloc - 4)[0] else: @@ -1232,8 +1393,11 @@ break code >>= 2 if kind == self.DESCR_FLOAT: - value = allregisters[2*code] - value_hi = allregisters[2*code + 1] + if WORD == 4: + value = allregisters[2*code] + value_hi = allregisters[2*code + 1] + else: + value = allregisters[code] else: value = allregisters[16 + code] @@ -1244,7 +1408,8 @@ tgt = self.fail_boxes_ptr.get_addr_for_num(num) elif kind == self.DESCR_FLOAT: tgt = self.fail_boxes_float.get_addr_for_num(num) - rffi.cast(rffi.LONGP, tgt)[1] = value_hi + if WORD == 4: + rffi.cast(rffi.LONGP, tgt)[1] = value_hi else: assert 0, "bogus kind" rffi.cast(rffi.LONGP, tgt)[0] = value @@ -1252,7 +1417,9 @@ # if not we_are_translated(): assert bytecode[4] == 0xCC - fail_index = rffi.cast(rffi.LONGP, bytecode)[0] + # fail_index = rffi.cast(rffi.LONGP, bytecode)[0] + fail_index = rffi.cast(rffi.INTP, bytecode)[0] + fail_index = rffi.cast(lltype.Signed, fail_index) return fail_index def setup_failure_recovery(self): @@ -1264,7 +1431,7 @@ # value of XMM registers, and finally a reference to the # recovery bytecode. See _build_failure_recovery() for details. stack_at_ebp = registers[ebp.value] - bytecode = rffi.cast(rffi.UCHARP, registers[8]) + bytecode = rffi.cast(rffi.UCHARP, registers[self.cpu.NUM_REGS]) allregisters = rffi.ptradd(registers, -16) return self.grab_frame_values(bytecode, stack_at_ebp, allregisters) @@ -1283,18 +1450,18 @@ # Assume that we are called at the beginning, when there is no risk # that 'mc' runs out of space. Checked by asserts in mc.write(). recovery_addr = mc.tell() - mc.PUSH(edi) - mc.PUSH(esi) - mc.PUSH(ebp) - mc.PUSH(esp) # <-- not really used, but needed to take up the space - mc.PUSH(ebx) - mc.PUSH(edx) - mc.PUSH(ecx) - mc.PUSH(eax) - mc.MOV_rr(esi.value, esp.value) + + # Push all general purpose registers + for gpr in reversed(range(self.cpu.NUM_REGS)): + mc.PUSH_r(gpr) + + # ebx/rbx is callee-save in both i386 and x86-64 + mc.MOV_rr(ebx.value, esp.value) + if withfloats: - mc.SUB_ri(esp.value, 8*8) - for i in range(8): + # Push all float registers + mc.SUB_ri(esp.value, self.cpu.NUM_REGS*8) + for i in range(self.cpu.NUM_REGS): mc.MOVSD_sx(8*i, i) # we call a provided function that will @@ -1313,19 +1480,24 @@ # bytecode, pushed just before by the CALL instruction written by # generate_quick_failure(). XXX misaligned stack in the call, but # it's ok because failure_recovery_func is not calling anything more - mc.PUSH(esi) + + # XXX + if mc.WORD == 4: + mc.PUSH(ebx) + elif mc.WORD == 8: + mc.MOV(edi, ebx) + # XXX: Correct to only align the stack on 64-bit? + mc.AND_ri(esp.value, -16) + else: + raise AssertionError("Shouldn't happen") + mc.CALL_l(failure_recovery_func) # returns in eax the fail_index # now we return from the complete frame, which starts from # _assemble_bootstrap_code(). The LEA below throws away most # of the frame, including all the PUSHes that we did just above. - mc.LEA_rb(esp.value, -3 * WORD) - mc.POP(edi) # [ebp-12] - mc.POP(esi) # [ebp-8] - mc.POP(ebx) # [ebp-4] - mc.POP(ebp) # [ebp] - mc.RET() + self._call_footer(mc) self.mc2.done() self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr @@ -1334,15 +1506,15 @@ for i in range(len(locs)): loc = locs[i] if isinstance(loc, RegLoc): - if loc.width == 8: + if loc.is_xmm: adr = self.fail_boxes_float.get_addr_for_num(i) - mc.MOVSD_jx(adr, loc.value) + mc.MOVSD(heap(adr), loc) else: if locs_are_ref[i]: adr = self.fail_boxes_ptr.get_addr_for_num(i) else: adr = self.fail_boxes_int.get_addr_for_num(i) - mc.MOV_jr(adr, loc.value) + mc.MOV(heap(adr), loc) for i in range(len(locs)): loc = locs[i] if not isinstance(loc, RegLoc): @@ -1350,14 +1522,14 @@ assert isinstance(loc, StackLoc) mc.MOVSD_xb(xmm0.value, loc.value) adr = self.fail_boxes_float.get_addr_for_num(i) - mc.MOVSD_jx(adr, xmm0.value) + mc.MOVSD(heap(adr), xmm0) else: if locs_are_ref[i]: adr = self.fail_boxes_ptr.get_addr_for_num(i) else: adr = self.fail_boxes_int.get_addr_for_num(i) mc.MOV(eax, loc) - mc.MOV_jr(adr, eax.value) + mc.MOV(heap(adr), eax) # we call a provided function that will # - call our on_leave_jitted_hook which will mark @@ -1367,13 +1539,10 @@ addr = self.cpu.get_on_leave_jitted_int(save_exception=exc) mc.CALL_l(addr) - mc.LEA_rb(esp.value, -3 * WORD) mc.MOV(eax, imm(fail_index)) - mc.POP(edi) # [ebp-12] - mc.POP(esi) # [ebp-8] - mc.POP(ebx) # [ebp-4] - mc.POP(ebp) # [ebp] - mc.RET() + + # exit function + self._call_footer(mc) # FIXME: I changed the third argument to this method, but I don't know # what to do with @specialize @@ -1401,7 +1570,7 @@ self._emit_call(x, arglocs, 2, tmp=tmp) - if isinstance(resloc, StackLoc) and resloc.width == 8: + if isinstance(resloc, StackLoc) and resloc.width == 8 and WORD == 4: self.mc.FSTP_b(resloc.value) elif size == 1: self.mc.AND(eax, imm(0xff)) @@ -1445,10 +1614,10 @@ assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, StackLoc) and result_loc.width == 8: + if WORD == 4 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: self.mc.FSTP_b(result_loc.value) else: - assert result_loc is eax or result_loc is None + assert result_loc is eax or result_loc is xmm0 or result_loc is None self.mc.CMP_bi(FORCE_INDEX_OFS, 0) return self.implement_guard(addr, 'L') @@ -1469,6 +1638,11 @@ # we choose the most compact encoding over the most efficient one. for i in range(len(arglocs)-1, -1, -1): mc.PUSH(arglocs[i]) + + if WORD == 8: + mc.MOV_rs(edi.value, 0) + mc.MOV_rs(esi.value, 8) + # misaligned stack in the call, but it's ok because the write barrier # is not going to call anything more. Also, this assumes that the # write barrier does not touch the xmm registers. Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py Sat Jun 12 00:19:21 2010 @@ -2,13 +2,19 @@ import os, sys from pypy.rpython.lltypesystem import lltype, rffi from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.jit.backend.x86.rx86 import X86_32_CodeBuilder +from pypy.jit.backend.x86.rx86 import X86_32_CodeBuilder, X86_64_CodeBuilder from pypy.jit.backend.x86.regloc import LocationCodeBuilder from pypy.rlib.rmmap import PTR, alloc, free from pypy.rlib.debug import make_sure_not_resized +from pypy.jit.backend.x86.regalloc import WORD +# XXX: Seems nasty to change the superclass of InMemoryCodeBuilder like this +if WORD == 4: + codebuilder_cls = X86_32_CodeBuilder +elif WORD == 8: + codebuilder_cls = X86_64_CodeBuilder -class InMemoryCodeBuilder(X86_32_CodeBuilder, LocationCodeBuilder): +class InMemoryCodeBuilder(codebuilder_cls, LocationCodeBuilder): _last_dump_start = 0 def __init__(self, start, end): @@ -53,11 +59,6 @@ self._pos = pos self._last_dump_start = pos - def execute(self, arg1, arg2): - # XXX old testing stuff - fnptr = rffi.cast(lltype.Ptr(BINARYFN), self._data) - return fnptr(arg1, arg2) - def done(self): # normally, no special action is needed here if machine_code_dumper.enabled: @@ -80,9 +81,6 @@ valgrind.discard_translations(self._data, self._size) -BINARYFN = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) - - class MachineCodeDumper: enabled = True log_fd = -1 @@ -110,7 +108,10 @@ return False # log the executable name from pypy.jit.backend.hlinfo import highleveljitinfo - os.write(self.log_fd, 'BACKEND i386\n') + if WORD == 4: + os.write(self.log_fd, 'BACKEND x86\n') + elif WORD == 8: + os.write(self.log_fd, 'BACKEND x86_64\n') if highleveljitinfo.sys_executable: os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % ( highleveljitinfo.sys_executable,)) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Sat Jun 12 00:19:21 2010 @@ -17,15 +17,27 @@ from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\ TempBox -WORD = 4 -FRAME_FIXED_SIZE = 5 # ebp + ebx + esi + edi + force_index = 5 words -FORCE_INDEX_OFS = -4*WORD - -width_of_type = { - INT : 1, - REF : 1, - FLOAT : 2, +# XXX +import sys +if sys.maxint == (2**31 - 1): + WORD = 4 + FRAME_FIXED_SIZE = 5 # ebp + ebx + esi + edi + force_index = 5 words + FORCE_INDEX_OFS = -4*WORD + width_of_type = { + INT : 1, + REF : 1, + FLOAT : 2, } +else: + WORD = 8 + FRAME_FIXED_SIZE = 7 + FORCE_INDEX_OFS = -6*WORD + width_of_type = { + INT : 1, + REF : 1, + FLOAT : 1, + } + class X86RegisterManager(RegisterManager): @@ -51,6 +63,12 @@ print "convert_to_imm: got a %s" % c raise AssertionError +class X86_64_RegisterManager(X86RegisterManager): + # r11 omitted because it's used as scratch + all_regs = [eax, ecx, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14, r15] + no_lower_byte_regs = [] + save_around_call_regs = [eax, ecx, edx, esi, edi, r8, r9, r10] + class FloatConstants(object): BASE_CONSTANT_SIZE = 1000 @@ -102,6 +120,20 @@ # after the call return self.frame_manager.loc(v) +class X86_64_XMMRegisterManager(X86XMMRegisterManager): + # xmm15 reserved for scratch use + all_regs = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14] + save_around_call_regs = all_regs + + def call_result_location(self, v): + return xmm0 + + def after_call(self, v): + # We use RegisterManager's implementation, since X86XMMRegisterManager + # places the result on the stack, which we don't need to do when the + # calling convention places the result in xmm0 + return RegisterManager.after_call(self, v) + class X86FrameManager(FrameManager): @staticmethod @@ -134,11 +166,21 @@ # compute longevity of variables longevity = self._compute_vars_longevity(inputargs, operations) self.longevity = longevity - self.rm = X86RegisterManager(longevity, - frame_manager = self.fm, - assembler = self.assembler) - self.xrm = X86XMMRegisterManager(longevity, frame_manager = self.fm, - assembler = self.assembler) + # XXX + if cpu.WORD == 4: + gpr_reg_mgr_cls = X86RegisterManager + xmm_reg_mgr_cls = X86XMMRegisterManager + elif cpu.WORD == 8: + gpr_reg_mgr_cls = X86_64_RegisterManager + xmm_reg_mgr_cls = X86_64_XMMRegisterManager + else: + raise AssertionError("Word size should be 4 or 8") + + self.rm = gpr_reg_mgr_cls(longevity, + frame_manager = self.fm, + assembler = self.assembler) + self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm, + assembler = self.assembler) def prepare_loop(self, inputargs, operations, looptoken): self._prepare(inputargs, operations) @@ -263,11 +305,11 @@ else: self.fm.frame_bindings[arg] = loc self.rm.free_regs = [] - for reg in X86RegisterManager.all_regs: + for reg in self.rm.all_regs: if reg not in used: self.rm.free_regs.append(reg) self.xrm.free_regs = [] - for reg in X86XMMRegisterManager.all_regs: + for reg in self.xrm.all_regs: if reg not in used: self.xrm.free_regs.append(reg) # note: we need to make a copy of inputargs because possibly_free_vars @@ -680,7 +722,7 @@ # function, a GC write barrier, is known not to touch them. # See remember_young_pointer() in rpython/memory/gc/generation.py. for v, reg in self.rm.reg_bindings.items(): - if ((reg is eax or reg is ecx or reg is edx) + if (reg in self.rm.save_around_call_regs and self.rm.stays_alive(v)): arglocs.append(reg) self.PerformDiscard(op, arglocs) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Sat Jun 12 00:19:21 2010 @@ -141,10 +141,15 @@ def value_m(self): return self.loc_m -REGLOCS = [RegLoc(i, is_xmm=False) for i in range(8)] -XMMREGLOCS = [RegLoc(i, is_xmm=True) for i in range(8)] -eax, ecx, edx, ebx, esp, ebp, esi, edi = REGLOCS -xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 = XMMREGLOCS +REGLOCS = [RegLoc(i, is_xmm=False) for i in range(16)] +XMMREGLOCS = [RegLoc(i, is_xmm=True) for i in range(16)] +eax, ecx, edx, ebx, esp, ebp, esi, edi, r8, r9, r10, r11, r12, r13, r14, r15 = REGLOCS +xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 = XMMREGLOCS + +X86_64_SCRATCH_REG = r11 +# XXX: a GPR scratch register is definitely needed, but we could probably do +# without an xmm scratch reg. +X86_64_XMM_SCRATCH_REG = xmm15 unrolling_location_codes = unrolling_iterable(list("rbsmajix")) @@ -159,14 +164,23 @@ if code1 == possible_code1: for possible_code2 in unrolling_location_codes: if code2 == possible_code2: - methname = name + "_" + possible_code1 + possible_code2 - if hasattr(rx86.AbstractX86CodeBuilder, methname): - val1 = getattr(loc1, "value_" + possible_code1)() - val2 = getattr(loc2, "value_" + possible_code2)() - getattr(self, methname)(val1, val2) - return + # FIXME: Not RPython anymore! + # Fake out certain operations for x86_64 + val1 = getattr(loc1, "value_" + possible_code1)() + val2 = getattr(loc2, "value_" + possible_code2)() + # XXX: Could use RIP+disp32 in some cases + if self.WORD == 8 and possible_code1 == 'j': + self.MOV_ri(X86_64_SCRATCH_REG.value, val1) + getattr(self, name + "_" + "m" + possible_code2)((X86_64_SCRATCH_REG.value, 0), val2) + elif self.WORD == 8 and possible_code2 == 'j': + self.MOV_ri(X86_64_SCRATCH_REG.value, val2) + getattr(self, name + "_" + possible_code1 + "m")(val1, (X86_64_SCRATCH_REG.value, 0)) + elif self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2) and name != 'MOV': + self.MOV_ri(X86_64_SCRATCH_REG.value, val2) + getattr(self, name + "_" + possible_code1 + "r")(val1, X86_64_SCRATCH_REG.value) else: - raise AssertionError("Instruction not defined: " + methname) + methname = name + "_" + possible_code1 + possible_code2 + getattr(self, methname)(val1, val2) return INSN @@ -176,7 +190,8 @@ for possible_code in unrolling_location_codes: if code == possible_code: methname = name + "_" + possible_code - if hasattr(rx86.AbstractX86CodeBuilder, methname): + # if hasattr(rx86.AbstractX86CodeBuilder, methname): + if hasattr(self, methname): val = getattr(loc, "value_" + possible_code)() getattr(self, methname)(val) return @@ -217,9 +232,11 @@ MOV16 = _16_bit_binaryop('MOV') MOVZX8 = _binaryop('MOVZX8') MOVZX16 = _binaryop('MOVZX16') + MOV32 = _binaryop('MOV32') + XCHG = _binaryop('XCHG') - PUSH = _unaryop("PUSH") - POP = _unaryop("POP") + PUSH = _unaryop('PUSH') + POP = _unaryop('POP') LEA = _binaryop('LEA') @@ -232,6 +249,9 @@ CVTSI2SD = _binaryop('CVTSI2SD') CVTTSD2SI = _binaryop('CVTTSD2SI') + ANDPD = _binaryop('ANDPD') + XORPD = _binaryop('XORPD') + CALL = _unaryop('CALL') def imm(x): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Sat Jun 12 00:19:21 2010 @@ -6,6 +6,8 @@ from pypy.jit.backend.x86.regalloc import FORCE_INDEX_OFS from pypy.jit.backend.x86.profagent import ProfileAgent from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU +from pypy.jit.backend.x86 import regloc +import sys class AbstractX86CPU(AbstractLLCPU): debug = True @@ -130,13 +132,27 @@ return faildescr class CPU386(AbstractX86CPU): - pass + WORD = 4 + NUM_REGS = 8 + CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi] + FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2 + + def __init__(self, *args, **kwargs): + assert sys.maxint == (2**31 - 1) + super(CPU386, self).__init__(*args, **kwargs) class CPU386_NO_SSE2(CPU386): supports_floats = False class CPU_X86_64(AbstractX86CPU): - pass + WORD = 8 + NUM_REGS = 16 + CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15] + FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2 + + def __init__(self, *args, **kwargs): + assert sys.maxint == (2**63 - 1) + super(CPU_X86_64, self).__init__(*args, **kwargs) CPU = CPU386 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Sat Jun 12 00:19:21 2010 @@ -32,10 +32,13 @@ xmmnames = ['xmm%d' % i for i in range(16)] def low_byte(reg): - assert 0 <= reg < 4 + # XXX: On 32-bit, this only works for 0 <= reg < 4 + # Maybe we should check this? return reg | BYTE_REG_FLAG def high_byte(reg): + # This probably shouldn't be called in 64-bit mode, since to use the + # high-byte registers you have to make sure that there is no REX-prefix assert 0 <= reg < 4 return (reg + 4) | BYTE_REG_FLAG @@ -83,13 +86,18 @@ return encode_register, argnum, factor, rex_register @specialize.arg(2) +def rex_byte_register(mc, reg, factor): + assert reg & BYTE_REG_FLAG + return rex_register(mc, reg & ~BYTE_REG_FLAG, factor) + + at specialize.arg(2) def encode_byte_register(mc, reg, factor, orbyte): assert reg & BYTE_REG_FLAG return encode_register(mc, reg & ~BYTE_REG_FLAG, factor, orbyte) def byte_register(argnum, factor=1): assert factor in (1, 8) - return encode_byte_register, argnum, factor, rex_register + return encode_byte_register, argnum, factor, rex_byte_register # ____________________________________________________________ @@ -310,6 +318,7 @@ arg = args[arg] orbyte = encode_step(mc, arg, extra, orbyte) assert orbyte == 0 + # encoding_steps = [] for step in encoding: @@ -431,26 +440,29 @@ mem_reg_plus_scaled_reg_plus_const(1)) MOV_ai = insn(rex_w, '\xC7', orbyte(0<<3), mem_reg_plus_scaled_reg_plus_const(1), immediate(2)) - # "MOV reg1, [immediate2]" and the opposite direction - MOV_rj = insn(rex_w, '\x8B', register(1,8), '\x05', immediate(2)) - MOV_jr = insn(rex_w, '\x89', register(2,8), '\x05', immediate(1)) - MOV_ji = insn(rex_w, '\xC7', '\x05', immediate(1), immediate(2)) MOV8_mr = insn(rex_w, '\x88', byte_register(2, 8), mem_reg_plus_const(1)) MOV8_ar = insn(rex_w, '\x88', byte_register(2, 8), mem_reg_plus_scaled_reg_plus_const(1)) MOV8_mi = insn(rex_w, '\xC6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) MOV8_ai = insn(rex_w, '\xC6', orbyte(0<<3), mem_reg_plus_scaled_reg_plus_const(1), immediate(2, 'b')) - MOV8_ji = insn(rex_w, '\xC6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b')) - MOV8_jr = insn(rex_w, '\x88', byte_register(2, 8), '\x05', immediate(1)) MOVZX8_rr = insn(rex_w, '\x0F\xB6', register(1,8), byte_register(2), '\xC0') MOVZX8_rm = insn(rex_w, '\x0F\xB6', register(1,8), mem_reg_plus_const(2)) MOVZX8_ra = insn(rex_w, '\x0F\xB6', register(1,8), mem_reg_plus_scaled_reg_plus_const(2)) - MOVZX8_rj = insn(rex_w, '\x0F\xB6', register(1,8), '\x05', immediate(2)) MOVZX16_rm = insn(rex_w, '\x0F\xB7', register(1,8), mem_reg_plus_const(2)) MOVZX16_ra = insn(rex_w, '\x0F\xB7', register(1,8), mem_reg_plus_scaled_reg_plus_const(2)) + # FIXME: Only difference between MOV32 and MOV instructions is rex_nw instead of rex_w + MOV32_ra = insn(rex_nw, '\x8B', register(1,8), + mem_reg_plus_scaled_reg_plus_const(2)) + MOV32_ar = insn(rex_nw, '\x89', register(2,8), + mem_reg_plus_scaled_reg_plus_const(1)) + MOV32_rm = insn(rex_nw, '\x8B', register(1,8), mem_reg_plus_const(2)) + MOV32_mr = insn(rex_nw, '\x89', register(2,8), mem_reg_plus_const(1)) + MOV32_mi = insn(rex_nw, '\xC7', orbyte(0<<3), mem_reg_plus_const(1), + immediate(2, 'i')) + # ------------------------------ Arithmetic ------------------------------ ADD_ri, ADD_rr, ADD_rb, _, _ = common_modes(0) @@ -464,11 +476,7 @@ CMP_mi32 = insn(rex_w, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) - CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2)) - CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - - CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2)) + CMP_rm = insn(rex_w, '\x3B', register(1, 8), mem_reg_plus_const(2)) AND8_rr = insn(rex_w, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -515,12 +523,9 @@ CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) CALL_b = insn('\xFF', orbyte(2<<3), stack_bp(1)) - # XXX: Bit of kludge, but works in 32-bit because the relative 32-bit - # displacement is always enough to encode any address - CALL_j = CALL_l XCHG_rm = insn(rex_w, '\x87', register(1,8), mem_reg_plus_const(2)) - XCHG_rj = insn(rex_w, '\x87', register(1,8), '\x05', immediate(2)) + XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') JMP_l = insn('\xE9', relative(1)) # FIXME: J_il8 and JMP_l8 assume the caller will do the appropriate @@ -530,7 +535,7 @@ J_il8 = insn(immediate(1, 'o'), '\x70', immediate(2, 'b')) J_il = insn('\x0F', immediate(1,'o'), '\x80', relative(2)) - SET_ir = insn('\x0F', immediate(1,'o'),'\x90', byte_register(2), '\xC0') + SET_ir = insn(rex_w, '\x0F', immediate(1,'o'),'\x90', byte_register(2), '\xC0') # The 64-bit version of this, CQO, is defined in X86_64_CodeBuilder CDQ = insn(rex_nw, '\x99') @@ -556,30 +561,28 @@ mem_reg_plus_const(1)) MOVSD_ax = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2,8), mem_reg_plus_scaled_reg_plus_const(1)) - MOVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1, 8), '\x05', immediate(2)) - MOVSD_jx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2, 8), '\x05', immediate(1)) # Arithmetic ADDSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), register(2), '\xC0') ADDSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), stack_bp(2)) - ADDSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), '\x05', immediate(2)) + ADDSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), mem_reg_plus_const(2)) SUBSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), register(2), '\xC0') SUBSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), stack_bp(2)) - SUBSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), '\x05', immediate(2)) + SUBSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), mem_reg_plus_const(2)) MULSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), register(2), '\xC0') MULSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), stack_bp(2)) - MULSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), '\x05', immediate(2)) + MULSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), mem_reg_plus_const(2)) DIVSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), register(2), '\xC0') DIVSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), stack_bp(2)) - DIVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), '\x05', immediate(2)) + DIVSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), mem_reg_plus_const(2)) # Comparision UCOMISD_xx = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), register(2), '\xC0') UCOMISD_xb = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), stack_bp(2)) - UCOMISD_xj = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), '\x05', immediate(2)) + UCOMISD_xm = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), mem_reg_plus_const(2)) # Conversion CVTSI2SD_xr = xmminsn('\xF2', rex_w, '\x0F\x2A', register(1, 8), register(2), '\xC0') @@ -589,10 +592,11 @@ CVTTSD2SI_rb = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), stack_bp(2)) # Bitwise - ANDPD_xj = xmminsn('\x66', rex_nw, '\x0F\x54', register(1, 8), '\x05', immediate(2)) XORPD_xx = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), register(2), '\xC0') - XORPD_xj = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), '\x05', immediate(2)) + XORPD_xm = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), mem_reg_plus_const(2)) + + ANDPD_xm = xmminsn('\x66', rex_nw, '\x0F\x54', register(1, 8), mem_reg_plus_const(2)) # ------------------------------------------------------------ @@ -619,6 +623,35 @@ class X86_32_CodeBuilder(AbstractX86CodeBuilder): WORD = 4 + # We can do direct memory references on 32-bit + MOV_rj = insn(rex_w, '\x8B', register(1,8), '\x05', immediate(2)) + MOV_jr = insn(rex_w, '\x89', register(2,8), '\x05', immediate(1)) + MOV_ji = insn(rex_w, '\xC7', '\x05', immediate(1), immediate(2)) + MOV8_ji = insn(rex_w, '\xC6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b')) + MOV8_jr = insn(rex_w, '\x88', byte_register(2, 8), '\x05', immediate(1)) + MOVZX8_rj = insn(rex_w, '\x0F\xB6', register(1,8), '\x05', immediate(2)) + + CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2)) + CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) + CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2)) + + # XXX: Bit of kludge, but works in 32-bit because the relative 32-bit + # displacement is always enough to encode any address + CALL_j = AbstractX86CodeBuilder.CALL_l + + XCHG_rj = insn(rex_w, '\x87', register(1,8), '\x05', immediate(2)) + + MOVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1, 8), '\x05', immediate(2)) + MOVSD_jx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2, 8), '\x05', immediate(1)) + ADDSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), '\x05', immediate(2)) + SUBSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), '\x05', immediate(2)) + MULSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), '\x05', immediate(2)) + DIVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), '\x05', immediate(2)) + UCOMISD_xj = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), '\x05', immediate(2)) + ANDPD_xj = xmminsn('\x66', rex_nw, '\x0F\x54', register(1, 8), '\x05', immediate(2)) + XORPD_xj = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), '\x05', immediate(2)) + class X86_64_CodeBuilder(AbstractX86CodeBuilder): WORD = 8 @@ -655,8 +688,18 @@ AbstractX86CodeBuilder.MOV_ri(self, R.eax, target) AbstractX86CodeBuilder.CALL_r(self, R.eax) + # XXX + CALL_j = CALL_l + # ____________________________________________________________ -all_instructions = [name for name in AbstractX86CodeBuilder.__dict__ - if name.split('_')[0].isupper()] +# FIXME: What about 32-bit only or 64-bit only instructions? +# This is used to build the MachineCodeBlockWrapper. Missing +# some instructions could possibly lead to subtle bugs. + +# FIXME: hack hack hack +all_instructions = ([name for name in AbstractX86CodeBuilder.__dict__ + if name.split('_')[0].isupper()] + + [name for name in X86_64_CodeBuilder.__dict__ + if name.split('_')[0].isupper()]) all_instructions.sort() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Sat Jun 12 00:19:21 2010 @@ -4,11 +4,15 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT from pypy.rlib.rarithmetic import intmask from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.detect_cpu import getcpuclass +ACTUAL_CPU = getcpuclass() class FakeCPU: rtyper = None supports_floats = True + NUM_REGS = ACTUAL_CPU.NUM_REGS class FakeMC: def __init__(self, base_address=0): @@ -46,12 +50,12 @@ xmm2] assert len(failargs) == len(locs) assembler.write_failure_recovery_description(mc, failargs, locs) - nums = [Assembler386.DESCR_INT + 4*(8+0), - Assembler386.DESCR_REF + 4*(8+1), - Assembler386.DESCR_FLOAT + 4*(8+10), - Assembler386.DESCR_INT + 4*(8+100), - Assembler386.DESCR_REF + 4*(8+101), - Assembler386.DESCR_FLOAT + 4*(8+110), + nums = [Assembler386.DESCR_INT + 4*(16+0), + Assembler386.DESCR_REF + 4*(16+1), + Assembler386.DESCR_FLOAT + 4*(16+10), + Assembler386.DESCR_INT + 4*(16+100), + Assembler386.DESCR_REF + 4*(16+101), + Assembler386.DESCR_FLOAT + 4*(16+110), Assembler386.CODE_HOLE, Assembler386.CODE_HOLE, Assembler386.DESCR_INT + 4*ebx.value, @@ -169,8 +173,8 @@ assert loc >= 0 ofs = get_ebp_ofs(loc) assert ofs < 0 - assert (ofs % 4) == 0 - stack[stacklen + ofs//4] = value + assert (ofs % WORD) == 0 + stack[stacklen + ofs//WORD] = value descr_bytecode = [] for i, (kind, loc) in enumerate(content): @@ -207,7 +211,7 @@ if isinstance(loc, RegLoc): num = kind + 4*loc.value else: - num = kind + 4*(8+loc) + num = kind + Assembler386.CODE_FROMSTACK + (4*loc) while num >= 0x80: descr_bytecode.append((num & 0x7F) | 0x80) num >>= 7 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py Sat Jun 12 00:19:21 2010 @@ -8,7 +8,7 @@ from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription -from pypy.jit.backend.x86.runner import CPU +from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.x86.regalloc import RegAlloc, WORD, FRAME_FIXED_SIZE from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.lltypesystem import lltype, llmemory, rffi @@ -22,6 +22,8 @@ X86XMMRegisterManager from pypy.rpython.annlowlevel import llhelper +CPU = getcpuclass() + class MockGcRootMap(object): def get_basic_shape(self): return ['shape'] @@ -83,7 +85,7 @@ mark = regalloc.get_mark_gc_roots(cpu.gc_ll_descr.gcrootmap) assert mark[0] == 'compressed' base = -WORD * FRAME_FIXED_SIZE - expected = ['ebx', 'esi', 'edi', base, base-4, base-8] + expected = ['ebx', 'esi', 'edi', base, base-WORD, base-WORD*2] assert dict.fromkeys(mark[1:]) == dict.fromkeys(expected) class TestRegallocGcIntegration(BaseTestRegalloc): @@ -174,7 +176,7 @@ self.addrs[1] = self.addrs[0] + 64 # 64 bytes def malloc_slowpath(size): - assert size == 8 + assert size == WORD*2 nadr = rffi.cast(lltype.Signed, self.nursery) self.addrs[0] = nadr + size return nadr @@ -198,7 +200,7 @@ return rffi.cast(lltype.Signed, self.addrs) def get_nursery_top_addr(self): - return rffi.cast(lltype.Signed, self.addrs) + 4 + return rffi.cast(lltype.Signed, self.addrs) + WORD def get_malloc_fixedsize_slowpath_addr(self): fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath) @@ -212,7 +214,7 @@ def setup_method(self, method): cpu = CPU(None, None) - cpu.vtable_offset = 4 + cpu.vtable_offset = WORD cpu.gc_ll_descr = GCDescrFastpathMalloc() NODE = lltype.Struct('node', ('tid', lltype.Signed), @@ -246,7 +248,7 @@ assert gc_ll_descr.nursery[0] == self.nodedescr.tid assert gc_ll_descr.nursery[1] == 42 nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + 8 + assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2) def test_malloc_slowpath(self): ops = ''' @@ -266,7 +268,7 @@ # this should call slow path once gc_ll_descr = self.cpu.gc_ll_descr nadr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nadr + 8 + assert gc_ll_descr.addrs[0] == nadr + (WORD*2) def test_new_with_vtable(self): ops = ''' @@ -281,4 +283,4 @@ assert gc_ll_descr.nursery[0] == self.descrsize.tid assert gc_ll_descr.nursery[1] == self.vtable_int nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + 8 + assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py Sat Jun 12 00:19:21 2010 @@ -1,6 +1,5 @@ - -from pypy.jit.backend.x86.runner import CPU from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc +from pypy.jit.backend.x86.regalloc import WORD class TestRecompilation(BaseTestRegalloc): def test_compile_bridge_not_deeper(self): @@ -51,7 +50,9 @@ descr = loop.operations[2].descr new = descr._x86_bridge_frame_depth assert descr._x86_bridge_param_depth == 0 - assert new > previous + # XXX: Maybe add enough ops to force stack on 64-bit as well? + if WORD == 4: + assert new > previous self.cpu.set_future_value_int(0, 0) fail = self.run(loop) assert fail.identifier == 2 @@ -111,7 +112,9 @@ guard_op = loop.operations[5] loop_frame_depth = loop.token._x86_frame_depth assert loop.token._x86_param_depth == 0 - assert guard_op.descr._x86_bridge_frame_depth > loop_frame_depth + # XXX: Maybe add enough ops to force stack on 64-bit as well? + if WORD == 4: + assert guard_op.descr._x86_bridge_frame_depth > loop_frame_depth assert guard_op.descr._x86_bridge_param_depth == 0 self.cpu.set_future_value_int(0, 0) self.cpu.set_future_value_int(1, 0) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Sat Jun 12 00:19:21 2010 @@ -7,7 +7,7 @@ BoxPtr, ConstPtr, LoopToken, BasicFailDescr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache -from pypy.jit.backend.x86.runner import CPU +from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.x86.regalloc import RegAlloc, WORD, X86RegisterManager,\ FloatConstants from pypy.jit.metainterp.test.oparser import parse @@ -16,6 +16,7 @@ from pypy.rpython.lltypesystem import rclass, rstr from pypy.jit.backend.x86.rx86 import * +CPU = getcpuclass() class MockGcDescr(GcCache): def get_funcptr_for_new(self): return 123 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py Sat Jun 12 00:19:21 2010 @@ -2,7 +2,8 @@ from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ BoxPtr, ConstPtr, BasicFailDescr, LoopToken from pypy.jit.metainterp.resoperation import rop -from pypy.jit.backend.x86.runner import CPU +from pypy.jit.backend.detect_cpu import getcpuclass +CPU = getcpuclass() def test_bug_rshift(): v1 = BoxInt() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Sat Jun 12 00:19:21 2010 @@ -3,7 +3,7 @@ from pypy.jit.metainterp.history import ResOperation, LoopToken from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Box, BasicFailDescr) -from pypy.jit.backend.x86.runner import CPU +from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.x86.regalloc import WORD from pypy.jit.backend.llsupport import symbolic from pypy.jit.metainterp.resoperation import rop @@ -12,6 +12,8 @@ import ctypes import sys +CPU = getcpuclass() + class FakeStats(object): pass @@ -56,7 +58,7 @@ assert u.chars[3] == u'd' @staticmethod - def _resbuf(res, item_tp=ctypes.c_int): + def _resbuf(res, item_tp=ctypes.c_long): return ctypes.cast(res.value._obj.intval, ctypes.POINTER(item_tp)) def test_allocations(self): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py Sat Jun 12 00:19:21 2010 @@ -226,6 +226,8 @@ 'SUB_ri', 'XOR_ri'): if args[0] == rx86.R.eax: return [] # ADD EAX, constant: there is a special encoding + if methname == 'XCHG_rr' and rx86.R.eax in args: + return [] # special encoding if methname == 'MOV_rj' and args[0] == rx86.R.eax: return [] # MOV EAX, [immediate]: there is a special encoding if methname == 'MOV_jr' and args[1] == rx86.R.eax: @@ -262,9 +264,18 @@ print "Skipping %s" % methname return + # XXX: ugly way to deal with the differences between 32 and 64 bit + if not hasattr(self.X86_CodeBuilder, methname): + return + + # XXX: hack hack hack + if methname == 'WORD': + return + + print "Testing %s with argmodes=%r" % (instrname, argmodes) self.methname = methname - self.is_xmm_insn = getattr(getattr(rx86.AbstractX86CodeBuilder, + self.is_xmm_insn = getattr(getattr(self.X86_CodeBuilder, methname), 'is_xmm_insn', False) ilist = self.make_all_tests(methname, argmodes) oplist, as_code = self.run_test(methname, instrname, argmodes, ilist) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py Sat Jun 12 00:19:21 2010 @@ -1,6 +1,7 @@ import py from pypy.jit.backend.llsupport.symbolic import * from pypy.rpython.lltypesystem import lltype, rffi +from pypy.jit.backend.x86.regalloc import WORD # This test file is here and not in llsupport/test/ because it checks # that we get correct numbers for a 32-bit machine. @@ -19,32 +20,32 @@ ofs_z, size_z = get_field_token(S, 'z', False) # ofs_x might be 0 or not, depending on how we count the headers # but the rest should be as expected for a 386 machine - assert size_x == size_y == size_z == 4 + assert size_x == size_y == size_z == WORD assert ofs_x >= 0 - assert ofs_y == ofs_x + 4 - assert ofs_z == ofs_x + 8 + assert ofs_y == ofs_x + WORD + assert ofs_z == ofs_x + (WORD*2) def test_struct_size(): ofs_z, size_z = get_field_token(S, 'z', False) totalsize = get_size(S, False) - assert totalsize == ofs_z + 4 + assert totalsize == ofs_z + WORD def test_primitive_size(): - assert get_size(lltype.Signed, False) == 4 + assert get_size(lltype.Signed, False) == WORD assert get_size(lltype.Char, False) == 1 - assert get_size(lltype.Ptr(S), False) == 4 + assert get_size(lltype.Ptr(S), False) == WORD def test_array_token(): A = lltype.GcArray(lltype.Char) basesize, itemsize, ofs_length = get_array_token(A, False) - assert basesize >= 4 # at least the 'length', maybe some gc headers + assert basesize >= WORD # at least the 'length', maybe some gc headers assert itemsize == 1 - assert ofs_length == basesize - 4 + assert ofs_length == basesize - WORD A = lltype.GcArray(lltype.Signed) basesize, itemsize, ofs_length = get_array_token(A, False) - assert basesize >= 4 # at least the 'length', maybe some gc headers - assert itemsize == 4 - assert ofs_length == basesize - 4 + assert basesize >= WORD # at least the 'length', maybe some gc headers + assert itemsize == WORD + assert ofs_length == basesize - WORD def test_varsized_struct_size(): S1 = lltype.GcStruct('S1', ('parent', S), @@ -54,9 +55,9 @@ ofs_extra, size_extra = get_field_token(S1, 'extra', False) basesize, itemsize, ofs_length = get_array_token(S1, False) assert size_parent == ofs_extra - assert size_extra == 4 - assert ofs_length == ofs_extra + 4 - assert basesize == ofs_length + 4 + assert size_extra == WORD + assert ofs_length == ofs_extra + WORD + assert basesize == ofs_length + WORD assert itemsize == 1 def test_string(): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zll_random.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zll_random.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zll_random.py Sat Jun 12 00:19:21 2010 @@ -1,9 +1,11 @@ from pypy.jit.backend.test.test_random import check_random_function, Random from pypy.jit.backend.test.test_ll_random import LLtypeOperationBuilder -from pypy.jit.backend.x86.runner import CPU386 +from pypy.jit.backend.detect_cpu import getcpuclass + +CPU = getcpuclass() def test_stress(): - cpu = CPU386(None, None) + cpu = CPU(None, None) r = Random() for i in range(1000): check_random_function(cpu, LLtypeOperationBuilder, r, i, 1000) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/tool/viewcode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/tool/viewcode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/tool/viewcode.py Sat Jun 12 00:19:21 2010 @@ -31,16 +31,22 @@ if sys.platform == "win32": XXX # lots more in Psyco -def machine_code_dump(data, originaddr): - # the disassembler to use. 'objdump' writes GNU-style instructions. - # 'ndisasm' would use Intel syntax, but you need to fix the output parsing. - objdump = ('objdump -M intel -b binary -m i386 ' +def machine_code_dump(data, originaddr, backend_name): + objdump_backend_option = { + 'x86': 'i386', + 'x86_64': 'x86-64', + } + objdump = ('objdump -M intel,%(backend)s -b binary -m i386 ' '--adjust-vma=%(origin)d -D %(file)s') # f = open(tmpfile, 'wb') f.write(data) f.close() - g = os.popen(objdump % {'file': tmpfile, 'origin': originaddr}, 'r') + g = os.popen(objdump % { + 'file': tmpfile, + 'origin': originaddr, + 'backend': objdump_backend_option[backend_name], + }, 'r') result = g.readlines() g.close() return result[6:] # drop some objdump cruft @@ -126,7 +132,7 @@ def disassemble(self): if not hasattr(self, 'text'): - lines = machine_code_dump(self.data, self.addr) + lines = machine_code_dump(self.data, self.addr, self.world.backend_name) # instead of adding symbol names in the dumps we could # also make the 0xNNNNNNNN addresses be red and show the # symbol name when the mouse is over them @@ -171,10 +177,13 @@ self.jumps = {} self.symbols = {} self.logentries = {} + self.backend_name = None def parse(self, f, textonly=True): for line in f: - if line.startswith('CODE_DUMP '): + if line.startswith('BACKEND '): + self.backend_name = line.split(' ')[1].strip() + elif line.startswith('CODE_DUMP '): pieces = line.split() assert pieces[1].startswith('@') assert pieces[2].startswith('+') From fijal at codespeak.net Sat Jun 12 06:06:31 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 06:06:31 +0200 (CEST) Subject: [pypy-svn] r75297 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20100612040631.8B6B4282BF2@codespeak.net> Author: fijal Date: Sat Jun 12 06:06:29 2010 New Revision: 75297 Modified: pypy/build/bot2/pypybuildbot/builds.py pypy/build/bot2/pypybuildbot/test/test_builds.py Log: A test and a fix Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sat Jun 12 06:06:29 2010 @@ -25,7 +25,8 @@ masterdest = os.path.join(masterdest, branch) if not os.path.exists(masterdest): os.makedirs(masterdest) - masterdest = os.path.join(masterdest, self.basename) + basename = WithProperties(self.basename).render(properties) + masterdest = os.path.join(masterdest, basename) self.masterdest = masterdest transfer.FileUpload.start(self) Modified: pypy/build/bot2/pypybuildbot/test/test_builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_builds.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_builds.py Sat Jun 12 06:06:29 2010 @@ -5,6 +5,8 @@ def __getitem__(self, item): if item == 'branch': return None + if item == 'got_revision': + return 123 def render(self, x): return x @@ -48,7 +50,7 @@ def test_pypy_upload(): pth = py.test.ensuretemp('buildbot') inst = builds.PyPyUpload(slavesrc='slavesrc', masterdest=str(pth.join('mstr')), - basename='base', workdir='.', + basename='base-%(got_revision)s', workdir='.', blocksize=100) factory, kw = inst.factory rebuilt = factory(**kw) @@ -57,3 +59,4 @@ rebuilt.runCommand = lambda *args: FakeDeferred() rebuilt.start() assert pth.join('mstr').check(dir=True) + assert rebuilt.masterdest == str(pth.join('mstr', 'trunk', 'base-123')) From fijal at codespeak.net Sat Jun 12 07:35:01 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 07:35:01 +0200 (CEST) Subject: [pypy-svn] r75298 - pypy/build/bot2/pypybuildbot Message-ID: <20100612053501.DEF2B36C537@codespeak.net> Author: fijal Date: Sat Jun 12 07:34:59 2010 New Revision: 75298 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: An attempt to fix stuff on windows, let's see if it'll work Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sat Jun 12 07:34:59 2010 @@ -134,9 +134,17 @@ "--resultlog=pypyjit.log", "pypy/module/pypyjit/test"], logfiles={'pytestLog': 'pypyjit.log'})) - self.addStep(ShellCmd( - description="compress pypy-c", - command=["bzip2", "-kf", "pypy/translator/goal/pypy-c"])) + if platform != 'win32': + self.addStep(ShellCmd( + description="compress pypy-c", + command=["bzip2", "-kf", "pypy/translator/goal/pypy-c"])) + else: + self.addStep(ShellCmd( + description="compress pypy-c", + command=["python", "-c", "from bz2 import BZ2File; " + "BZ2File('pypy/translator/goal/pypy-c.bz2', 'w')" + ".write(open('pypy/translator/goal/pypy-c.exe'" + ", 'rb').read())"])) if pypyjit: kind = 'jit' else: From arigo at codespeak.net Sat Jun 12 09:25:12 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:25:12 +0200 (CEST) Subject: [pypy-svn] r75299 - pypy/branch/multijit-4 Message-ID: <20100612072512.2E6B8282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:25:09 2010 New Revision: 75299 Added: pypy/branch/multijit-4/ - copied from r75298, pypy/trunk/ Log: Bring the branch up-to-date with the current trunk, including r75289 (fast path of CALL_ASSEMBLER). From arigo at codespeak.net Sat Jun 12 09:32:19 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:32:19 +0200 (CEST) Subject: [pypy-svn] r75300 - in pypy/branch/multijit-4/pypy/jit: codewriter codewriter/test metainterp metainterp/test Message-ID: <20100612073219.960E8282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:32:17 2010 New Revision: 75300 Added: pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py - copied unchanged from r75299, pypy/branch/multijit-3/pypy/jit/metainterp/jitdriver.py Modified: pypy/branch/multijit-4/pypy/jit/codewriter/call.py pypy/branch/multijit-4/pypy/jit/codewriter/codewriter.py pypy/branch/multijit-4/pypy/jit/codewriter/jitcode.py pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py pypy/branch/multijit-4/pypy/jit/codewriter/test/test_call.py pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-4/pypy/jit/metainterp/compile.py pypy/branch/multijit-4/pypy/jit/metainterp/history.py pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/resume.py pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Log: Merge branch/multijit-3. Modified: pypy/branch/multijit-4/pypy/jit/codewriter/call.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/call.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/call.py Sat Jun 12 09:32:17 2010 @@ -16,21 +16,22 @@ class CallControl(object): virtualref_info = None # optionally set from outside - virtualizable_info = None # optionally set from outside - portal_runner_ptr = None # optionally set from outside - def __init__(self, cpu=None, portal_graph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): + assert isinstance(jitdrivers_sd, list) # debugging self.cpu = cpu - self.portal_graph = portal_graph + self.jitdrivers_sd = jitdrivers_sd self.jitcodes = {} # map {graph: jitcode} self.unfinished_graphs = [] # list of graphs with pending jitcodes - self.jitdriver = None if hasattr(cpu, 'rtyper'): # for tests self.rtyper = cpu.rtyper translator = self.rtyper.annotator.translator self.raise_analyzer = RaiseAnalyzer(translator) self.readwrite_analyzer = ReadWriteAnalyzer(translator) self.virtualizable_analyzer = VirtualizableAnalyzer(translator) + # + for index, jd in enumerate(jitdrivers_sd): + jd.index = index def find_all_graphs(self, policy): try: @@ -41,8 +42,8 @@ def is_candidate(graph): return policy.look_inside_graph(graph) - assert self.portal_graph is not None - todo = [self.portal_graph] + assert len(self.jitdrivers_sd) > 0 + todo = [jd.portal_graph for jd in self.jitdrivers_sd] if hasattr(self, 'rtyper'): for oopspec_name, ll_args, ll_res in support.inline_calls_to: c_func, _ = support.builtin_func_for_spec(self.rtyper, @@ -122,7 +123,7 @@ def guess_call_kind(self, op, is_candidate=None): if op.opname == 'direct_call': funcptr = op.args[0].value - if funcptr is self.portal_runner_ptr: + if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None: return 'recursive' funcobj = get_funcobj(funcptr) if getattr(funcobj, 'graph', None) is None: @@ -143,6 +144,11 @@ # used only after find_all_graphs() return graph in self.candidate_graphs + def grab_initial_jitcodes(self): + for jd in self.jitdrivers_sd: + jd.mainjitcode = self.get_jitcode(jd.portal_graph) + jd.mainjitcode.is_portal = True + def enum_pending_graphs(self): while self.unfinished_graphs: graph = self.unfinished_graphs.pop() @@ -241,12 +247,26 @@ return (effectinfo is None or effectinfo.extraeffect >= EffectInfo.EF_CAN_RAISE) - def found_jitdriver(self, jitdriver): - if self.jitdriver is None: - self.jitdriver = jitdriver - else: - assert self.jitdriver is jitdriver + def jitdriver_sd_from_portal_graph(self, graph): + for jd in self.jitdrivers_sd: + if jd.portal_graph is graph: + return jd + return None - def getjitdriver(self): - assert self.jitdriver is not None, "order dependency issue?" - return self.jitdriver + def jitdriver_sd_from_portal_runner_ptr(self, funcptr): + for jd in self.jitdrivers_sd: + if funcptr is jd.portal_runner_ptr: + return jd + return None + + def get_vinfo(self, VTYPEPTR): + seen = set() + for jd in self.jitdrivers_sd: + if jd.virtualizable_info is not None: + if jd.virtualizable_info.is_vtypeptr(VTYPEPTR): + seen.add(jd.virtualizable_info) + if seen: + assert len(seen) == 1 + return seen.pop() + else: + return None Modified: pypy/branch/multijit-4/pypy/jit/codewriter/codewriter.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/codewriter.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/codewriter.py Sat Jun 12 09:32:17 2010 @@ -14,29 +14,30 @@ class CodeWriter(object): callcontrol = None # for tests - def __init__(self, cpu=None, maingraph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): self.cpu = cpu self.assembler = Assembler() - self.portal_graph = maingraph - self.callcontrol = CallControl(cpu, maingraph) + self.callcontrol = CallControl(cpu, jitdrivers_sd) + self._seen_files = set() def transform_func_to_jitcode(self, func, values, type_system='lltype'): """For testing.""" rtyper = support.annotate(func, values, type_system=type_system) graph = rtyper.annotator.translator.graphs[0] jitcode = JitCode("test") - self.transform_graph_to_jitcode(graph, jitcode, True, True) + self.transform_graph_to_jitcode(graph, jitcode, True) return jitcode - def transform_graph_to_jitcode(self, graph, jitcode, portal, verbose): + def transform_graph_to_jitcode(self, graph, jitcode, verbose): """Transform a graph into a JitCode containing the same bytecode in a different format. """ + portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph) graph = copygraph(graph, shallowvars=True) # # step 1: mangle the graph so that it contains the final instructions # that we want in the JitCode, but still as a control flow graph - transform_graph(graph, self.cpu, self.callcontrol, portal) + transform_graph(graph, self.cpu, self.callcontrol, portal_jd) # # step 2: perform register allocation on it regallocs = {} @@ -59,16 +60,14 @@ self.assembler.assemble(ssarepr, jitcode) # # print the resulting assembler - self.print_ssa_repr(ssarepr, portal, verbose) + self.print_ssa_repr(ssarepr, portal_jd, verbose) def make_jitcodes(self, verbose=False): log.info("making JitCodes...") - maingraph = self.portal_graph - self.mainjitcode = self.callcontrol.get_jitcode(maingraph) + self.callcontrol.grab_initial_jitcodes() count = 0 for graph, jitcode in self.callcontrol.enum_pending_graphs(): - self.transform_graph_to_jitcode(graph, jitcode, - graph is maingraph, verbose) + self.transform_graph_to_jitcode(graph, jitcode, verbose) count += 1 if not count % 500: log.info("Produced %d jitcodes" % count) @@ -76,33 +75,35 @@ log.info("there are %d JitCode instances." % count) def setup_vrefinfo(self, vrefinfo): + # must be called at most once + assert self.callcontrol.virtualref_info is None self.callcontrol.virtualref_info = vrefinfo - def setup_virtualizable_info(self, vinfo): - self.callcontrol.virtualizable_info = vinfo - - def setup_portal_runner_ptr(self, portal_runner_ptr): - self.callcontrol.portal_runner_ptr = portal_runner_ptr + def setup_jitdriver(self, jitdriver_sd): + # Must be called once per jitdriver. Usually jitdriver_sd is an + # instance of pypy.jit.metainterp.jitdriver.JitDriverStaticData. + self.callcontrol.jitdrivers_sd.append(jitdriver_sd) def find_all_graphs(self, policy): return self.callcontrol.find_all_graphs(policy) - def print_ssa_repr(self, ssarepr, portal, verbose): + def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose): if verbose: print '%s:' % (ssarepr.name,) print format_assembler(ssarepr) else: dir = udir.ensure("jitcodes", dir=1) - if portal: - name = "00_portal_runner" + if portal_jitdriver: + name = "%02d_portal_runner" % (portal_jitdriver.index,) elif ssarepr.name and ssarepr.name != '?': name = ssarepr.name else: name = 'unnamed' % id(ssarepr) i = 1 extra = '' - while dir.join(name+extra).check(exists=1): + while name+extra in self._seen_files: i += 1 extra = '.%d' % i + self._seen_files.add(name+extra) dir.join(name+extra).write(format_assembler(ssarepr)) log.dot() Modified: pypy/branch/multijit-4/pypy/jit/codewriter/jitcode.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/jitcode.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/jitcode.py Sat Jun 12 09:32:17 2010 @@ -13,6 +13,7 @@ self.name = name self.fnaddr = fnaddr self.calldescr = calldescr + self.is_portal = False self._called_from = called_from # debugging self._ssarepr = None # debugging @@ -24,11 +25,11 @@ self.constants_i = constants_i or self._empty_i self.constants_r = constants_r or self._empty_r self.constants_f = constants_f or self._empty_f - # encode the three num_regs into a single integer + # encode the three num_regs into a single char each assert num_regs_i < 256 and num_regs_r < 256 and num_regs_f < 256 - self.num_regs_encoded = ((num_regs_i << 16) | - (num_regs_f << 8) | - (num_regs_r << 0)) + self.c_num_regs_i = chr(num_regs_i) + self.c_num_regs_r = chr(num_regs_r) + self.c_num_regs_f = chr(num_regs_f) self.liveness = make_liveness_cache(liveness) self._startpoints = startpoints # debugging self._alllabels = alllabels # debugging @@ -37,13 +38,13 @@ return heaptracker.adr2int(self.fnaddr) def num_regs_i(self): - return self.num_regs_encoded >> 16 - - def num_regs_f(self): - return (self.num_regs_encoded >> 8) & 0xFF + return ord(self.c_num_regs_i) def num_regs_r(self): - return self.num_regs_encoded & 0xFF + return ord(self.c_num_regs_r) + + def num_regs_f(self): + return ord(self.c_num_regs_f) def has_liveness_info(self, pc): return pc in self.liveness Modified: pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py Sat Jun 12 09:32:17 2010 @@ -13,23 +13,23 @@ from pypy.translator.simplify import get_funcobj -def transform_graph(graph, cpu=None, callcontrol=None, portal=True): +def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None): """Transform a control flow graph to make it suitable for being flattened in a JitCode. """ - t = Transformer(cpu, callcontrol) - t.transform(graph, portal) + t = Transformer(cpu, callcontrol, portal_jd) + t.transform(graph) class Transformer(object): - def __init__(self, cpu=None, callcontrol=None): + def __init__(self, cpu=None, callcontrol=None, portal_jd=None): self.cpu = cpu self.callcontrol = callcontrol + self.portal_jd = portal_jd # non-None only for the portal graph(s) - def transform(self, graph, portal): + def transform(self, graph): self.graph = graph - self.portal = portal for block in list(graph.iterblocks()): self.optimize_block(block) @@ -325,10 +325,12 @@ return op1 def handle_recursive_call(self, op): - ops = self.promote_greens(op.args[1:]) - targetgraph = self.callcontrol.portal_graph - num_green_args = len(self.callcontrol.getjitdriver().greens) - args = (self.make_three_lists(op.args[1:1+num_green_args]) + + jitdriver_sd = self.callcontrol.jitdriver_sd_from_portal_runner_ptr( + op.args[0]) + ops = self.promote_greens(op.args[1:], jitdriver_sd.jitdriver) + num_green_args = len(jitdriver_sd.jitdriver.greens) + args = ([Constant(jitdriver_sd.index, lltype.Signed)] + + self.make_three_lists(op.args[1:1+num_green_args]) + self.make_three_lists(op.args[1+num_green_args:])) kind = getkind(op.result.concretetype)[0] op0 = SpaceOperation('recursive_call_%s' % kind, args, op.result) @@ -483,14 +485,14 @@ # check for virtualizable try: if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('getfield_vable_%s' % kind, [v_inst, descr], op.result)] - except VirtualizableArrayField: + except VirtualizableArrayField, e: # xxx hack hack hack - vinfo = self.callcontrol.virtualizable_info + vinfo = e.args[1] arrayindex = vinfo.array_field_counter[op.args[1].value] arrayfielddescr = vinfo.array_field_descrs[arrayindex] arraydescr = vinfo.array_descrs[arrayindex] @@ -527,7 +529,7 @@ return # check for virtualizable if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('setfield_vable_%s' % kind, @@ -544,21 +546,23 @@ return (op.args[1].value == 'typeptr' and op.args[0].concretetype.TO._hints.get('typeptr')) + def get_vinfo(self, v_virtualizable): + if self.callcontrol is None: # for tests + return None + return self.callcontrol.get_vinfo(v_virtualizable.concretetype) + def is_virtualizable_getset(self, op): # every access of an object of exactly the type VTYPEPTR is # likely to be a virtualizable access, but we still have to # check it in pyjitpl.py. - try: - vinfo = self.callcontrol.virtualizable_info - except AttributeError: - return False - if vinfo is None or not vinfo.is_vtypeptr(op.args[0].concretetype): + vinfo = self.get_vinfo(op.args[0]) + if vinfo is None: return False res = False if op.args[1].value in vinfo.static_field_to_extra_box: res = True if op.args[1].value in vinfo.array_fields: - res = VirtualizableArrayField(self.graph) + res = VirtualizableArrayField(self.graph, vinfo) if res: flags = self.vable_flags[op.args[0]] @@ -568,8 +572,9 @@ raise res return res - def get_virtualizable_field_descr(self, fieldname): - vinfo = self.callcontrol.virtualizable_info + def get_virtualizable_field_descr(self, op): + fieldname = op.args[1].value + vinfo = self.get_vinfo(op.args[0]) index = vinfo.static_field_to_extra_box[fieldname] return vinfo.static_field_descrs[index] @@ -750,9 +755,10 @@ return Constant(value, lltype.Bool) return op - def promote_greens(self, args): + def promote_greens(self, args, jitdriver): ops = [] - num_green_args = len(self.callcontrol.getjitdriver().greens) + num_green_args = len(jitdriver.greens) + assert len(args) == num_green_args + len(jitdriver.reds) for v in args[:num_green_args]: if isinstance(v, Variable) and v.concretetype is not lltype.Void: kind = getkind(v.concretetype) @@ -762,20 +768,24 @@ return ops def rewrite_op_jit_marker(self, op): - self.callcontrol.found_jitdriver(op.args[1].value) key = op.args[0].value - return getattr(self, 'handle_jit_marker__%s' % key)(op) + jitdriver = op.args[1].value + return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver) - def handle_jit_marker__jit_merge_point(self, op): - assert self.portal, "jit_merge_point in non-main graph!" - ops = self.promote_greens(op.args[2:]) - num_green_args = len(self.callcontrol.getjitdriver().greens) - args = (self.make_three_lists(op.args[2:2+num_green_args]) + + def handle_jit_marker__jit_merge_point(self, op, jitdriver): + assert self.portal_jd is not None, ( + "'jit_merge_point' in non-portal graph!") + assert jitdriver is self.portal_jd.jitdriver, ( + "general mix-up of jitdrivers?") + ops = self.promote_greens(op.args[2:], jitdriver) + num_green_args = len(jitdriver.greens) + args = ([Constant(self.portal_jd.index, lltype.Signed)] + + self.make_three_lists(op.args[2:2+num_green_args]) + self.make_three_lists(op.args[2+num_green_args:])) op1 = SpaceOperation('jit_merge_point', args, None) return ops + [op1] - def handle_jit_marker__can_enter_jit(self, op): + def handle_jit_marker__can_enter_jit(self, op, jitdriver): return SpaceOperation('can_enter_jit', [], None) def rewrite_op_debug_assert(self, op): @@ -974,9 +984,8 @@ def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables - vinfo = self.callcontrol.virtualizable_info + vinfo = self.get_vinfo(op.args[0]) assert vinfo is not None - assert vinfo.is_vtypeptr(op.args[0].concretetype) self.vable_flags[op.args[0]] = op.args[2].value return [] Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_call.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_call.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_call.py Sat Jun 12 09:32:17 2010 @@ -52,13 +52,19 @@ # ____________________________________________________________ +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + def test_find_all_graphs(): def g(x): return x + 2 def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) res = cc.find_all_graphs(FakePolicy()) funcs = set([graph.func for graph in res]) assert funcs == set([f, g]) @@ -69,7 +75,8 @@ def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) class CustomFakePolicy: def look_inside_graph(self, graph): assert graph.name == 'g' @@ -83,10 +90,11 @@ def test_guess_call_kind_and_calls_from_graphs(): class portal_runner_obj: graph = object() + class FakeJitDriverSD: + portal_runner_ptr = portal_runner_obj g = object() g1 = object() - cc = CallControl() - cc.portal_runner_ptr = portal_runner_obj + cc = CallControl(jitdrivers_sd=[FakeJitDriverSD()]) cc.candidate_graphs = [g, g1] op = SpaceOperation('direct_call', [Constant(portal_runner_obj)], Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py Sat Jun 12 09:32:17 2010 @@ -35,6 +35,12 @@ def look_inside_graph(self, graph): return graph.name != 'dont_look' +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + self.virtualizable_info = None + def test_loop(): def f(a, b): @@ -70,11 +76,11 @@ def fff(a, b): return ggg(b) - ggg(a) rtyper = support.annotate(fff, [35, 42]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) - jitcode = cw.mainjitcode + jitcode = jitdriver_sd.mainjitcode print jitcode.dump() [jitcode2] = cw.assembler.descrs print jitcode2.dump() @@ -117,7 +123,7 @@ return x().id + y().id + dont_look(n) rtyper = support.annotate(f, [35]) maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # @@ -144,10 +150,10 @@ def f(n): return abs(n) rtyper = support.annotate(f, [35]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # - s = cw.mainjitcode.dump() + s = jitdriver_sd.mainjitcode.dump() assert "inline_call_ir_i " in s Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py Sat Jun 12 09:32:17 2010 @@ -68,11 +68,8 @@ return FakeDescr() def calldescr_canraise(self, calldescr): return calldescr is not self._descr_cannot_raise - def found_jitdriver(self, jitdriver): - assert isinstance(jitdriver, JitDriver) - self.jitdriver = jitdriver - def getjitdriver(self): - return self.jitdriver + def get_vinfo(self, VTYPEPTR): + return None class FakeCallControlWithVRefInfo: class virtualref_info: @@ -118,13 +115,13 @@ return self.rtyper.annotator.translator.graphs def encoding_test(self, func, args, expected, - transform=False, liveness=False, cc=None): + transform=False, liveness=False, cc=None, jd=None): graphs = self.make_graphs(func, args) #graphs[0].show() if transform: from pypy.jit.codewriter.jtransform import transform_graph cc = cc or FakeCallControl() - transform_graph(graphs[0], FakeCPU(self.rtyper), cc) + transform_graph(graphs[0], FakeCPU(self.rtyper), cc, jd) ssarepr = flatten_graph(graphs[0], fake_regallocs(), _include_all_exc_links=not transform) if liveness: @@ -584,13 +581,16 @@ def f(x, y): myjitdriver.jit_merge_point(x=x, y=y) myjitdriver.can_enter_jit(x=y, y=x) + class FakeJitDriverSD: + jitdriver = myjitdriver + index = 27 self.encoding_test(f, [4, 5], """ -live- %i0, %i1 int_guard_value %i0 - jit_merge_point I[%i0], R[], F[], I[%i1], R[], F[] + jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[] can_enter_jit void_return - """, transform=True, liveness=True) + """, transform=True, liveness=True, jd=FakeJitDriverSD()) def test_keepalive(self): S = lltype.GcStruct('S') Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Sat Jun 12 09:32:17 2010 @@ -315,27 +315,12 @@ def get_tmpreg_f(self): return self.tmpreg_f - def final_result_i(self): - assert self._return_type == 'i' - return self.get_tmpreg_i() - - def final_result_r(self): - assert self._return_type == 'r' - return self.get_tmpreg_r() - - def final_result_f(self): - assert self._return_type == 'f' - return self.get_tmpreg_f() - - def final_result_v(self): - assert self._return_type == 'v' - def _final_result_anytype(self): "NOT_RPYTHON" - if self._return_type == 'i': return self.final_result_i() - if self._return_type == 'r': return self.final_result_r() - if self._return_type == 'f': return self.final_result_f() - if self._return_type == 'v': return self.final_result_v() + if self._return_type == 'i': return self.get_tmpreg_i() + if self._return_type == 'r': return self.get_tmpreg_r() + if self._return_type == 'f': return self.get_tmpreg_v() + if self._return_type == 'v': return None raise ValueError(self._return_type) def cleanup_registers(self): @@ -775,8 +760,8 @@ def bhimpl_can_enter_jit(): pass - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_jit_merge_point(self, *args): + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_jit_merge_point(self, jdindex, *args): if self.nextblackholeinterp is None: # we are the last level CRN = self.builder.metainterp_sd.ContinueRunningNormally raise CRN(*args) @@ -790,55 +775,57 @@ # call the interpreter main loop from here, and just return its # result. sd = self.builder.metainterp_sd + xxxxxxxxxxxx if sd.result_type == 'void': - self.bhimpl_recursive_call_v(*args) + self.bhimpl_recursive_call_v(jdindex, *args) self.bhimpl_void_return() elif sd.result_type == 'int': - x = self.bhimpl_recursive_call_i(*args) + x = self.bhimpl_recursive_call_i(jdindex, *args) self.bhimpl_int_return(x) elif sd.result_type == 'ref': - x = self.bhimpl_recursive_call_r(*args) + x = self.bhimpl_recursive_call_r(jdindex, *args) self.bhimpl_ref_return(x) elif sd.result_type == 'float': - x = self.bhimpl_recursive_call_f(*args) + x = self.bhimpl_recursive_call_f(jdindex, *args) self.bhimpl_float_return(x) assert False - def get_portal_runner(self): + def get_portal_runner(self, jdindex): metainterp_sd = self.builder.metainterp_sd - fnptr = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + jitdriver_sd = metainterp_sd.jitdrivers_sd[jdindex] + fnptr = llmemory.cast_ptr_to_adr(jitdriver_sd.portal_runner_ptr) fnptr = heaptracker.adr2int(fnptr) - calldescr = metainterp_sd.portal_code.calldescr + calldescr = jitdriver_sd.mainjitcode.calldescr return fnptr, calldescr - @arguments("self", "I", "R", "F", "I", "R", "F", returns="i") - def bhimpl_recursive_call_i(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="i") + def bhimpl_recursive_call_i(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_i(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="r") - def bhimpl_recursive_call_r(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="r") + def bhimpl_recursive_call_r(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_r(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="f") - def bhimpl_recursive_call_f(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="f") + def bhimpl_recursive_call_f(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_f(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_recursive_call_v(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_recursive_call_v(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_v(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, @@ -1175,11 +1162,11 @@ self._done_with_this_frame() kind = self._return_type if kind == 'i': - caller._setup_return_value_i(self.final_result_i()) + caller._setup_return_value_i(self.get_tmpreg_i()) elif kind == 'r': - caller._setup_return_value_r(self.final_result_r()) + caller._setup_return_value_r(self.get_tmpreg_r()) elif kind == 'f': - caller._setup_return_value_f(self.final_result_f()) + caller._setup_return_value_f(self.get_tmpreg_f()) else: assert kind == 'v' return lltype.nullptr(rclass.OBJECTPTR.TO) @@ -1245,15 +1232,15 @@ # rare case: we only get there if the blackhole interps all returned # normally (in general we get a ContinueRunningNormally exception). sd = self.builder.metainterp_sd - if sd.result_type == 'void': - self.final_result_v() + kind = self._return_type + if kind == 'v': raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': - raise sd.DoneWithThisFrameInt(self.final_result_i()) - elif sd.result_type == 'ref': - raise sd.DoneWithThisFrameRef(self.cpu, self.final_result_r()) - elif sd.result_type == 'float': - raise sd.DoneWithThisFrameFloat(self.final_result_f()) + elif kind == 'i': + raise sd.DoneWithThisFrameInt(self.get_tmpreg_i()) + elif kind == 'r': + raise sd.DoneWithThisFrameRef(self.cpu, self.get_tmpreg_r()) + elif kind == 'f': + raise sd.DoneWithThisFrameFloat(self.get_tmpreg_f()) else: assert False @@ -1287,12 +1274,14 @@ blackholeinterp.builder.release_interp(blackholeinterp) blackholeinterp = blackholeinterp.nextblackholeinterp -def resume_in_blackhole(metainterp_sd, resumedescr, all_virtuals=None): +def resume_in_blackhole(metainterp_sd, jitdriver_sd, resumedescr, + all_virtuals=None): from pypy.jit.metainterp.resume import blackhole_from_resumedata debug_start('jit-blackhole') metainterp_sd.profiler.start_blackhole() blackholeinterp = blackhole_from_resumedata( metainterp_sd.blackholeinterpbuilder, + jitdriver_sd, resumedescr, all_virtuals) current_exc = blackholeinterp._prepare_resume_from_failure( Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/compile.py Sat Jun 12 09:32:17 2010 @@ -63,11 +63,12 @@ # make a copy, because optimize_loop can mutate the ops and descrs loop.operations = [op.clone() for op in ops] metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd loop_token = make_loop_token(len(loop.inputargs)) loop.token = loop_token loop.operations[-1].descr = loop_token # patch the target of the JUMP try: - old_loop_token = metainterp_sd.state.optimize_loop( + old_loop_token = jitdriver_sd._state.optimize_loop( metainterp_sd, old_loop_tokens, loop) except InvalidLoop: return None @@ -141,32 +142,32 @@ pass class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'void' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.VOID raise metainterp_sd.DoneWithThisFrameVoid() class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'int' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.INT result = metainterp_sd.cpu.get_latest_value_int(0) raise metainterp_sd.DoneWithThisFrameInt(result) class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'ref' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.REF cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'float' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.FLOAT result = metainterp_sd.cpu.get_latest_value_float(0) raise metainterp_sd.DoneWithThisFrameFloat(result) class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) @@ -258,22 +259,27 @@ # a negative value self._counter = cnt | i - def handle_fail(self, metainterp_sd): - if self.must_compile(metainterp_sd): - return self._trace_and_compile_from_bridge(metainterp_sd) + def handle_fail(self, metainterp_sd, jitdriver_sd): + if self.must_compile(metainterp_sd, jitdriver_sd): + return self._trace_and_compile_from_bridge(metainterp_sd, + jitdriver_sd) else: from pypy.jit.metainterp.blackhole import resume_in_blackhole - resume_in_blackhole(metainterp_sd, self) + resume_in_blackhole(metainterp_sd, jitdriver_sd, self) assert 0, "unreachable" - def _trace_and_compile_from_bridge(self, metainterp_sd): + def _trace_and_compile_from_bridge(self, metainterp_sd, jitdriver_sd): + # 'jitdriver_sd' corresponds to the outermost one, i.e. the one + # of the jit_merge_point where we started the loop, even if the + # loop itself may contain temporarily recursion into other + # jitdrivers. from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) return metainterp.handle_guard_failure(self) _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd): - trace_eagerness = metainterp_sd.state.trace_eagerness + def must_compile(self, metainterp_sd, jitdriver_sd): + trace_eagerness = jitdriver_sd._state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness @@ -333,7 +339,7 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): # Failures of a GUARD_NOT_FORCED are never compiled, but # always just blackholed. First fish for the data saved when # the virtualrefs and virtualizable have been forced by @@ -343,7 +349,7 @@ all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - resume_in_blackhole(metainterp_sd, self, all_virtuals) + resume_in_blackhole(metainterp_sd, jitdriver_sd, self, all_virtuals) assert 0, "unreachable" @staticmethod @@ -464,6 +470,7 @@ # a loop at all but ends in a jump to the target loop. It starts # with completely unoptimized arguments, as in the interpreter. metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd metainterp.history.inputargs = self.redkey new_loop_token = make_loop_token(len(self.redkey)) new_loop.greenkey = self.original_greenkey @@ -471,12 +478,11 @@ new_loop.token = new_loop_token send_loop_to_backend(metainterp_sd, new_loop, "entry bridge") # send the new_loop to warmspot.py, to be called directly the next time - metainterp_sd.state.attach_unoptimized_bridge_from_interp( + jitdriver_sd._state.attach_unoptimized_bridge_from_interp( self.original_greenkey, new_loop_token) # store the new loop in compiled_merge_points too - glob = metainterp_sd.globaldata - old_loop_tokens = glob.get_compiled_merge_points( + old_loop_tokens = metainterp.get_compiled_merge_points( self.original_greenkey) # it always goes at the end of the list, as it is the most # general loop token @@ -500,8 +506,9 @@ # clone ops, as optimize_bridge can mutate the ops new_loop.operations = [op.clone() for op in metainterp.history.operations] metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd try: - target_loop_token = metainterp_sd.state.optimize_bridge(metainterp_sd, + target_loop_token = jitdriver_sd._state.optimize_bridge(metainterp_sd, old_loop_tokens, new_loop) except InvalidLoop: Modified: pypy/branch/multijit-4/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/history.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/history.py Sat Jun 12 09:32:17 2010 @@ -174,7 +174,7 @@ class AbstractFailDescr(AbstractDescr): index = -1 - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): raise NotImplementedError def compile_and_attach(self, metainterp, new_loop): raise NotImplementedError Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 09:32:17 2010 @@ -56,6 +56,7 @@ self.parent_resumedata_snapshot = None self.parent_resumedata_frame_info_list = None + @specialize.arg(3) def copy_constants(self, registers, constants, ConstClass): """Copy jitcode.constants[0] to registers[255], jitcode.constants[1] to registers[254], @@ -68,7 +69,6 @@ assert j >= 0 registers[j] = ConstClass(constants[i]) i -= 1 - copy_constants._annspecialcase_ = 'specialize:arg(3)' def cleanup_registers(self): # To avoid keeping references alive, this cleans up the registers_r. @@ -80,6 +80,7 @@ # ------------------------------ # Decoding of the JitCode + @specialize.arg(4) def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): assert argcode in 'IRF' code = self.bytecode @@ -92,7 +93,6 @@ elif argcode == 'F': reg = self.registers_f[index] else: raise AssertionError(argcode) outvalue[startindex+i] = reg - prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' def get_current_position_info(self): return self.jitcode.get_live_vars_info(self.pc) @@ -518,15 +518,15 @@ return not isstandard def _get_virtualizable_field_index(self, fielddescr): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.array_field_descrs[index] def _get_virtualizable_array_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdrivers_sd.virtualizable_info return vinfo.array_descrs[index] @arguments("orgpc", "box", "descr") @@ -557,7 +557,8 @@ def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) - vinfo = self.metainterp.staticdata.virtualizable_info + xxxxxxx + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] @@ -606,7 +607,8 @@ arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, fdescr, box) return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) - vinfo = self.metainterp.staticdata.virtualizable_info + xxxxxxx + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[fdescr] @@ -655,10 +657,11 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("boxes3", "boxes3") - def _opimpl_recursive_call(self, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): allboxes = greenboxes + redboxes metainterp_sd = self.metainterp.staticdata + xxxx portal_code = metainterp_sd.portal_code warmrunnerstate = metainterp_sd.state token = None @@ -765,17 +768,18 @@ raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args + def verify_green_args(self, jdindex, varargs): + jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] + num_green_args = jitdriver.num_green_args assert len(varargs) == num_green_args for i in range(num_green_args): assert isinstance(varargs[i], Const) - @arguments("orgpc", "boxes3", "boxes3") - def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): - self.verify_green_args(greenboxes) + @arguments("orgpc", "int", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes): + self.verify_green_args(jdindex, greenboxes) # xxx we may disable the following line in some context later - self.debug_merge_point(greenboxes) + self.debug_merge_point(jdindex, greenboxes) if self.metainterp.seen_can_enter_jit: self.metainterp.seen_can_enter_jit = False # Assert that it's impossible to arrive here with in_recursion @@ -783,6 +787,7 @@ # to True by opimpl_can_enter_jit, which should be executed # just before opimpl_jit_merge_point (no recursion inbetween). assert not self.metainterp.in_recursion + assert jdindex == self.metainterp.jitdriver_sd.index # Set self.pc to point to jit_merge_point instead of just after: # if reached_can_enter_jit() raises SwitchToBlackhole, then the # pc is still at the jit_merge_point, which is a point that is @@ -792,10 +797,10 @@ self.metainterp.reached_can_enter_jit(greenboxes, redboxes) self.pc = saved_pc - def debug_merge_point(self, greenkey): + def debug_merge_point(self, jdindex, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - sd = self.metainterp.staticdata - loc = sd.state.get_location_str(greenkey) + jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] + loc = jitdriver._state.get_location_str(greenkey) debug_print(loc) constloc = self.metainterp.cpu.ts.conststr(loc) self.metainterp.history.record(rop.DEBUG_MERGE_POINT, @@ -945,7 +950,7 @@ guard_op = metainterp.history.record(opnum, moreargs, None, descr=resumedescr) virtualizable_boxes = None - if metainterp.staticdata.virtualizable_info is not None: + if metainterp.jitdriver_sd.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes saved_pc = self.pc if resumepc >= 0: @@ -1127,6 +1132,11 @@ self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] + def setup_jitdrivers_sd(self, optimizer): + if optimizer is not None: + for jd in self.jitdrivers_sd: + jd._state.set_param_optimizer(optimizer) + def finish_setup(self, codewriter, optimizer=None): from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) @@ -1137,28 +1147,21 @@ self.setup_indirectcalltargets(asm.indirectcalltargets) self.setup_list_of_addr2name(asm.list_of_addr2name) # - self.portal_code = codewriter.mainjitcode - self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.jitdrivers_sd = codewriter.callcontrol.jitdrivers_sd self.virtualref_info = codewriter.callcontrol.virtualref_info - self.virtualizable_info = codewriter.callcontrol.virtualizable_info - RESULT = codewriter.portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) + self.setup_jitdrivers_sd(optimizer) # # store this information for fastpath of call_assembler - name = self.result_type - tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) - num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) - setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # (only the paths that can actually be taken) + for jd in self.jitdrivers_sd: + name = {history.INT: 'int', + history.REF: 'ref', + history.FLOAT: 'float', + history.VOID: 'void'}[jd.result_type] + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) # - warmrunnerdesc = self.warmrunnerdesc - if warmrunnerdesc is not None: - self.num_green_args = warmrunnerdesc.num_green_args - self.state = warmrunnerdesc.state - if optimizer is not None: - self.state.set_param_optimizer(optimizer) - else: - self.num_green_args = 0 - self.state = None self.globaldata = MetaInterpGlobalData(self) def _setup_once(self): @@ -1179,8 +1182,7 @@ # Build the dictionary at run-time. This is needed # because the keys are function/class addresses, so they # can change from run to run. - k = llmemory.cast_ptr_to_adr(self._portal_runner_ptr) - d = {k: 'recursive call'} + d = {} keys = self._addr2name_keys values = self._addr2name_values for i in range(len(keys)): @@ -1238,47 +1240,31 @@ self.loopnumbering = 0 self.resume_virtuals = {} self.resume_virtuals_not_translated = [] - # - state = staticdata.state - if state is not None: - self.jit_cell_at_key = state.jit_cell_at_key - else: - # for tests only; not RPython - class JitCell: - compiled_merge_points = None - _jitcell_dict = {} - def jit_cell_at_key(greenkey): - greenkey = tuple(greenkey) - return _jitcell_dict.setdefault(greenkey, JitCell()) - self.jit_cell_at_key = jit_cell_at_key - - def get_compiled_merge_points(self, greenkey): - cell = self.jit_cell_at_key(greenkey) - if cell.compiled_merge_points is None: - cell.compiled_merge_points = [] - return cell.compiled_merge_points # ____________________________________________________________ class MetaInterp(object): in_recursion = 0 - def __init__(self, staticdata): + def __init__(self, staticdata, jitdriver_sd): self.staticdata = staticdata self.cpu = staticdata.cpu + self.jitdriver_sd = jitdriver_sd + # Note: self.jitdriver_sd is the JitDriverStaticData that corresponds + # to the current loop -- the outermost one. Be careful, because + # during recursion we can also see other jitdrivers. self.portal_trace_positions = [] self.free_frames_list = [] self.last_exc_value_box = None def perform_call(self, jitcode, boxes, greenkey=None): # causes the metainterp to enter the given subfunction - # with a special case for recursive portal calls f = self.newframe(jitcode, greenkey) f.setup_call(boxes) raise ChangeFrame def newframe(self, jitcode, greenkey=None): - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: self.in_recursion += 1 if greenkey is not None: self.portal_trace_positions.append( @@ -1293,7 +1279,7 @@ def popframe(self): frame = self.framestack.pop() - if frame.jitcode is self.staticdata.portal_code: + if frame.jitcode.is_portal: self.in_recursion -= 1 if frame.greenkey is not None: self.portal_trace_positions.append( @@ -1317,14 +1303,15 @@ except SwitchToBlackhole, stb: self.aborted_tracing(stb.reason) sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert resultbox is None raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': + elif result_type == history.INT: raise sd.DoneWithThisFrameInt(resultbox.getint()) - elif sd.result_type == 'ref': + elif result_type == history.REF: raise sd.DoneWithThisFrameRef(self.cpu, resultbox.getref_base()) - elif sd.result_type == 'float': + elif result_type == history.FLOAT: raise sd.DoneWithThisFrameFloat(resultbox.getfloat()) else: assert False @@ -1354,14 +1341,17 @@ in_recursion = -1 for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + assert jitcode.is_portal == len([ + jd for jd in self.staticdata.jitdrivers_sd + if jd.mainjitcode is jitcode]) + if jitcode.is_portal: in_recursion += 1 if in_recursion != self.in_recursion: print "in_recursion problem!!!" print in_recursion, self.in_recursion for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: print "P", else: print " ", @@ -1369,7 +1359,6 @@ raise AssertionError def create_empty_history(self): - warmrunnerstate = self.staticdata.state self.history = history.History() self.staticdata.stats.set_history(self.history) @@ -1479,12 +1468,11 @@ self.resumekey.reset_counter_from_failure() def blackhole_if_trace_too_long(self): - warmrunnerstate = self.staticdata.state + warmrunnerstate = self.jitdriver_sd._state if len(self.history.operations) > warmrunnerstate.trace_limit: greenkey_of_huge_function = self.find_biggest_function() self.portal_trace_positions = None if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state warmrunnerstate.disable_noninlinable_function( greenkey_of_huge_function) raise SwitchToBlackhole(ABORT_TOO_LONG) @@ -1511,21 +1499,27 @@ self.staticdata.log(sys.exc_info()[0].__name__) raise - def compile_and_run_once(self, *args): + @specialize.arg(1) + def compile_and_run_once(self, jitdriver_sd, *args): + # NB. we pass explicity 'jitdriver_sd' around here, even though it + # is also available as 'self.jitdriver_sd', because we need to + # specialize this function and a few other ones for the '*args'. debug_start('jit-tracing') self.staticdata._setup_once() self.staticdata.profiler.start_tracing() + assert jitdriver_sd is self.jitdriver_sd self.create_empty_history() try: - return self._compile_and_run_once(*args) + original_boxes = self.initialize_original_boxes(jitdriver_sd,*args) + return self._compile_and_run_once(original_boxes) finally: self.staticdata.profiler.end_tracing() debug_stop('jit-tracing') - def _compile_and_run_once(self, *args): - original_boxes = self.initialize_state_from_start(*args) + def _compile_and_run_once(self, original_boxes): + self.initialize_state_from_start(original_boxes) self.current_merge_points = [(original_boxes, 0)] - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args original_greenkey = original_boxes[:num_green_args] redkey = original_boxes[num_green_args:] self.resumekey = compile.ResumeFromInterpDescr(original_greenkey, @@ -1592,7 +1586,7 @@ self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) live_arg_boxes = greenboxes + redboxes - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, @@ -1614,11 +1608,12 @@ # Search in current_merge_points for original_boxes with compatible # green keys, representing the beginning of the same loop as the one # we end now. - + + num_green_args = self.jitdriver_sd.num_green_args for j in range(len(self.current_merge_points)-1, -1, -1): original_boxes, start = self.current_merge_points[j] assert len(original_boxes) == len(live_arg_boxes) or start < 0 - for i in range(self.staticdata.num_green_args): + for i in range(num_green_args): box1 = original_boxes[i] box2 = live_arg_boxes[i] assert isinstance(box1, Const) @@ -1641,7 +1636,7 @@ def designate_target_loop(self, gmp): loop_token = gmp.target_loop_token - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args residual_args = self.get_residual_args(loop_token.specnodes, gmp.argboxes[num_green_args:]) history.set_future_values(self.cpu, residual_args) @@ -1682,12 +1677,17 @@ from pypy.jit.metainterp.resoperation import opname raise NotImplementedError(opname[opnum]) + def get_compiled_merge_points(self, greenkey): + cell = self.jitdriver_sd._state.jit_cell_at_key(greenkey) + if cell.compiled_merge_points is None: + cell.compiled_merge_points = [] + return cell.compiled_merge_points + def compile(self, original_boxes, live_arg_boxes, start): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop_token = compile.compile_new_loop(self, old_loop_tokens, greenkey, start) @@ -1696,10 +1696,9 @@ self.history.operations.pop() # remove the JUMP def compile_bridge(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args greenkey = live_arg_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) if len(old_loop_tokens) == 0: return self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) @@ -1713,17 +1712,18 @@ self.gen_store_back_in_virtualizable() # temporarily put a JUMP to a pseudo-loop sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert exitbox is None exits = [] loop_tokens = sd.loop_tokens_done_with_this_frame_void - elif sd.result_type == 'int': + elif result_type == history.INT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_int - elif sd.result_type == 'ref': + elif result_type == history.REF: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_ref - elif sd.result_type == 'float': + elif result_type == history.FLOAT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_float else: @@ -1755,26 +1755,32 @@ specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args - def _initialize_from_start(self, original_boxes, num_green_args, *args): + @specialize.arg(1) + def initialize_original_boxes(self, jitdriver_sd, *args): + original_boxes = [] + self._fill_original_boxes(jitdriver_sd, original_boxes, + jitdriver_sd.num_green_args, *args) + return original_boxes + + @specialize.arg(1) + def _fill_original_boxes(self, jitdriver_sd, original_boxes, + num_green_args, *args): if args: from pypy.jit.metainterp.warmstate import wrap box = wrap(self.cpu, args[0], num_green_args > 0) original_boxes.append(box) - self._initialize_from_start(original_boxes, num_green_args-1, - *args[1:]) + self._fill_original_boxes(jitdriver_sd, original_boxes, + num_green_args-1, *args[1:]) - def initialize_state_from_start(self, *args): - self.in_recursion = -1 # always one portal around - num_green_args = self.staticdata.num_green_args - original_boxes = [] - self._initialize_from_start(original_boxes, num_green_args, *args) + def initialize_state_from_start(self, original_boxes): # ----- make a new frame ----- + self.in_recursion = -1 # always one portal around self.framestack = [] - f = self.newframe(self.staticdata.portal_code) + f = self.newframe(self.jitdriver_sd.mainjitcode) f.setup_call(original_boxes) + assert self.in_recursion == 0 self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) - return original_boxes def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack @@ -1784,7 +1790,7 @@ self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = original_boxes[vinfo.index_of_virtualizable] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1797,7 +1803,7 @@ self.initialize_virtualizable_enter() def initialize_virtualizable_enter(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.clear_vable_token(virtualizable) @@ -1811,7 +1817,7 @@ # the FORCE_TOKEN is already set at runtime in each vref when # it is created, by optimizeopt.py. # - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1837,7 +1843,7 @@ self.stop_tracking_virtualref(i) def vable_after_residual_call(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1888,7 +1894,7 @@ assert self.last_exc_value_box is None def rebuild_state_after_failure(self, resumedescr): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info self.framestack = [] boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists @@ -1924,13 +1930,13 @@ def check_synchronized_virtualizable(self): if not we_are_translated(): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.check_boxes(virtualizable, self.virtualizable_boxes) def synchronize_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.write_boxes(virtualizable, self.virtualizable_boxes) @@ -1939,7 +1945,7 @@ # Force a reload of the virtualizable fields into the local # boxes (called only in escaping cases). Only call this function # just before SwitchToBlackhole. - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1948,7 +1954,7 @@ self.virtualizable_boxes.append(virtualizable_box) def gen_store_back_in_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: # xxx only write back the fields really modified vbox = self.virtualizable_boxes[-1] @@ -1970,7 +1976,7 @@ assert i + 1 == len(self.virtualizable_boxes) def gen_load_from_other_virtualizable(self, vbox): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info boxes = [] assert vinfo is not None for i in range(vinfo.num_static_extra_boxes): @@ -1994,7 +2000,7 @@ for i in range(len(boxes)): if boxes[i] is oldbox: boxes[i] = newbox - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: boxes = self.virtualizable_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2050,8 +2056,9 @@ assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args args = op.args[num_green_args + 1:] - if self.staticdata.virtualizable_info is not None: - vindex = self.staticdata.virtualizable_info.index_of_virtualizable + vinfo = self.jitdriver_sd.virtualizable_info + if vinfo is not None: + vindex = vinfo.index_of_virtualizable vbox = args[vindex - num_green_args] args = args + self.gen_load_from_other_virtualizable(vbox) # ^^^ and not "+=", which makes 'args' a resizable list @@ -2156,6 +2163,16 @@ position = position3 + 1 + length3 elif argtype == "orgpc": value = orgpc + elif argtype == "int": + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = ord(code[position]) + elif argcode == 'c': + value = signedord(code[position]) + else: + raise AssertionError("bad argcode") + position += 1 else: raise AssertionError("bad argtype: %r" % (argtype,)) args += (value,) Modified: pypy/branch/multijit-4/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/resume.py Sat Jun 12 09:32:17 2010 @@ -709,11 +709,11 @@ # ---------- when resuming for blackholing, get direct values ---------- -def blackhole_from_resumedata(blackholeinterpbuilder, storage, +def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage, all_virtuals=None): resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, all_virtuals) - vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vinfo = jitdriver_sd.virtualizable_info vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info resumereader.consume_vref_and_vable(vrefinfo, vinfo) # Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 09:32:17 2010 @@ -16,10 +16,18 @@ from pypy.jit.codewriter import support, codewriter from pypy.jit.metainterp import simple_optimize + class FakeJitCell: + compiled_merge_points = None + class FakeWarmRunnerState: def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): pass + def jit_cell_at_key(self, greenkey): + assert greenkey == [] + return self._cell + _cell = FakeJitCell() + # pick the optimizer this way optimize_loop = staticmethod(simple_optimize.optimize_loop) optimize_bridge = staticmethod(simple_optimize.optimize_bridge) @@ -30,13 +38,22 @@ func._jit_unroll_safe_ = True rtyper = support.annotate(func, values, type_system=type_system) graphs = rtyper.annotator.translator.graphs + result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0] + + class FakeJitDriverSD: + num_green_args = 0 + portal_graph = graphs[0] + virtualizable_info = None + result_type = result_kind + portal_runner_ptr = "???" + stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - cw = codewriter.CodeWriter(cpu, graphs[0]) + cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()]) testself.cw = cw cw.find_all_graphs(JitPolicy()) # - testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate = FakeJitDriverSD._state = FakeWarmRunnerState() testself.warmrunnerstate.cpu = cpu if hasattr(testself, 'finish_setup_for_interp_operations'): testself.finish_setup_for_interp_operations() @@ -62,7 +79,8 @@ count_f += 1 else: raise TypeError(T) - blackholeinterp.setposition(cw.mainjitcode, 0) + [jitdriver_sd] = cw.callcontrol.jitdrivers_sd + blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0) blackholeinterp.run() return blackholeinterp._final_result_anytype() @@ -78,16 +96,15 @@ cw = testself.cw opt = history.Options(listops=True) metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) - metainterp_sd.finish_setup(cw, optimizer="bogus") - metainterp_sd.state = testself.warmrunnerstate - metainterp_sd.state.cpu = metainterp_sd.cpu - metainterp = pyjitpl.MetaInterp(metainterp_sd) + metainterp_sd.finish_setup(cw) + [jitdriver_sd] = metainterp_sd.jitdrivers_sd + metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd) metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame testself.metainterp = metainterp try: - metainterp.compile_and_run_once(*args) + metainterp.compile_and_run_once(jitdriver_sd, *args) except DoneWithThisFrame, e: #if conftest.option.view: # metainterp.stats.view() @@ -814,8 +831,9 @@ translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=self.CPUClass) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(0) # for tests + state = warmrunnerdesc.jitdrivers_sd[0]._state + state.set_param_threshold(3) # for tests + state.set_param_trace_eagerness(0) # for tests warmrunnerdesc.finish() for n, k in [(20, 0), (20, 1)]: interp.eval_graph(graph, [n, k]) Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 09:32:17 2010 @@ -21,6 +21,7 @@ from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.metainterp.jitdriver import JitDriverStaticData from pypy.jit.codewriter import support, codewriter from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE @@ -69,11 +70,12 @@ translator.config.translation.gc = "boehm" translator.config.translation.list_comprehension_operations = True warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests - warmrunnerdesc.state.set_param_trace_limit(trace_limit) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_debug(debug_level) + for jd in warmrunnerdesc.jitdrivers_sd: + jd._state.set_param_threshold(3) # for tests + jd._state.set_param_trace_eagerness(2) # for tests + jd._state.set_param_trace_limit(trace_limit) + jd._state.set_param_inlining(inline) + jd._state.set_param_debug(debug_level) warmrunnerdesc.finish() res = interp.eval_graph(graph, args) if not kwds.get('translate_support_code', False): @@ -110,12 +112,11 @@ raise Exception("no can_enter_jit found!") return results -def find_jit_merge_point(graphs): +def find_jit_merge_points(graphs): results = _find_jit_marker(graphs, 'jit_merge_point') - if len(results) != 1: - raise Exception("found %d jit_merge_points, need exactly one!" % - (len(results),)) - return results[0] + if not results: + raise Exception("no jit_merge_point found!") + return results def find_set_param(graphs): return _find_jit_marker(graphs, 'set_param') @@ -146,8 +147,8 @@ pyjitpl._warmrunnerdesc = self # this is a global for debugging only! self.set_translator(translator) self.build_cpu(CPUClass, **kwds) - self.find_portal() - self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + self.find_portals() + self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd) if policy is None: policy = JitPolicy() policy.set_supports_floats(self.cpu.supports_floats) @@ -158,35 +159,31 @@ self.prejit_optimizations(policy, graphs) self.build_meta_interp(ProfilerClass) - self.make_args_specification() + self.make_args_specifications() # from pypy.jit.metainterp.virtualref import VirtualRefInfo vrefinfo = VirtualRefInfo(self) self.codewriter.setup_vrefinfo(vrefinfo) - if self.jitdriver.virtualizables: - from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.virtualizable_info = VirtualizableInfo(self) - self.codewriter.setup_virtualizable_info(self.virtualizable_info) - else: - self.virtualizable_info = None # + self.make_virtualizable_infos() self.make_exception_classes() self.make_driverhook_graphs() - self.make_enter_function() - self.rewrite_jit_merge_point(policy) + self.make_enter_functions() + self.rewrite_jit_merge_points(policy) verbose = not self.cpu.translate_support_code self.codewriter.make_jitcodes(verbose=verbose) - self.rewrite_can_enter_jit() + self.rewrite_can_enter_jits() self.rewrite_set_param() self.rewrite_force_virtual(vrefinfo) self.add_finish() self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.virtualizable_info - if vinfo is not None: - vinfo.finish() + vinfos = set([jd.virtualizable_info for jd in self.jitdrivers_sd]) + for vinfo in vinfos: + if vinfo is not None: + vinfo.finish() if self.cpu.translate_support_code: self.annhelper.finish() @@ -198,18 +195,27 @@ self.rtyper = translator.rtyper self.gcdescr = gc.get_description(translator.config) - def find_portal(self): + def find_portals(self): + self.jitdrivers_sd = [] graphs = self.translator.graphs - self.jit_merge_point_pos = find_jit_merge_point(graphs) - graph, block, pos = self.jit_merge_point_pos + for jit_merge_point_pos in find_jit_merge_points(graphs): + self.split_graph_and_record_jitdriver(*jit_merge_point_pos) + # + assert (len(set([jd.jitdriver for jd in self.jitdrivers_sd])) == + len(self.jitdrivers_sd)), \ + "there are multiple jit_merge_points with the same jitdriver" + + def split_graph_and_record_jitdriver(self, graph, block, pos): + jd = JitDriverStaticData() + jd._jit_merge_point_pos = (graph, block, pos) op = block.operations[pos] args = op.args[2:] s_binding = self.translator.annotator.binding - self.portal_args_s = [s_binding(v) for v in args] + jd._portal_args_s = [s_binding(v) for v in args] graph = copygraph(graph) graph.startblock.isstartblock = False - graph.startblock = support.split_before_jit_merge_point( - *find_jit_merge_point([graph])) + [jmpp] = find_jit_merge_points([graph]) + graph.startblock = support.split_before_jit_merge_point(*jmpp) graph.startblock.isstartblock = True # a crash in the following checkgraph() means that you forgot # to list some variable in greens=[] or reds=[] in JitDriver. @@ -218,12 +224,16 @@ assert isinstance(v, Variable) assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs()) self.translator.graphs.append(graph) - self.portal_graph = graph + jd.portal_graph = graph # it's a bit unbelievable to have a portal without func assert hasattr(graph, "func") graph.func._dont_inline_ = True graph.func._jit_unroll_safe_ = True - self.jitdriver = block.operations[pos].args[1].value + jd.jitdriver = block.operations[pos].args[1].value + jd.portal_runner_ptr = "" + jd.result_type = history.getkind(jd.portal_graph.getreturnvar() + .concretetype)[0] + self.jitdrivers_sd.append(jd) def check_access_directly_sanity(self, graphs): from pypy.translator.backendopt.inline import collect_called_graphs @@ -268,6 +278,17 @@ ProfilerClass=ProfilerClass, warmrunnerdesc=self) + def make_virtualizable_infos(self): + for jd in self.jitdrivers_sd: + if jd.jitdriver.virtualizables: + XXX + from pypy.jit.metainterp.virtualizable import VirtualizableInfo + vinfo = VirtualizableInfo(self) + YYY # share! + else: + vinfo = None + jd.virtualizable_info = vinfo + def make_exception_classes(self): class DoneWithThisFrameVoid(JitException): @@ -317,6 +338,8 @@ self.green_int, self.green_ref, self.green_float, self.red_int, self.red_ref, self.red_float) + # XXX there is no point any more to not just have the exceptions + # as globals self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt self.DoneWithThisFrameRef = DoneWithThisFrameRef @@ -330,11 +353,15 @@ self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally - def make_enter_function(self): + def make_enter_functions(self): + for jd in self.jitdrivers_sd: + self.make_enter_function(jd) + + def make_enter_function(self, jd): from pypy.jit.metainterp.warmstate import WarmEnterState - state = WarmEnterState(self) + state = WarmEnterState(self, jd) maybe_compile_and_run = state.make_entry_point() - self.state = state + jd._state = state def crash_in_jit(e): if not we_are_translated(): @@ -359,15 +386,16 @@ def maybe_enter_jit(*args): maybe_compile_and_run(*args) maybe_enter_jit._always_inline_ = True - self.maybe_enter_jit_fn = maybe_enter_jit + jd._maybe_enter_jit_fn = maybe_enter_jit - can_inline = self.state.can_inline_greenargs + can_inline = state.can_inline_greenargs + num_green_args = jd.num_green_args def maybe_enter_from_start(*args): - if can_inline is not None and not can_inline(*args[:self.num_green_args]): + if can_inline is not None and not can_inline(*args[:num_green_args]): maybe_compile_and_run(*args) maybe_enter_from_start._always_inline_ = True - self.maybe_enter_from_start_fn = maybe_enter_from_start - + jd._maybe_enter_from_start_fn = maybe_enter_from_start + def make_driverhook_graphs(self): from pypy.rlib.jit import BaseJitCell bk = self.rtyper.annotator.bookkeeper @@ -378,22 +406,23 @@ s_Str = annmodel.SomeString() # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) - self.set_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.set_jitcell_at, annmodel.s_None, - s_BaseJitCell_not_None) - self.get_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) - self.can_inline_ptr = self._make_hook_graph( - annhelper, self.jitdriver.can_inline, annmodel.s_Bool) - self.get_printable_location_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_printable_location, s_Str) - self.confirm_enter_jit_ptr = self._make_hook_graph( - annhelper, self.jitdriver.confirm_enter_jit, annmodel.s_Bool, - onlygreens=False) + for jd in self.jitdrivers_sd: + jd._set_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.set_jitcell_at, annmodel.s_None, + s_BaseJitCell_not_None) + jd._get_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) + jd._can_inline_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.can_inline, annmodel.s_Bool) + jd._get_printable_location_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_printable_location, s_Str) + jd._confirm_enter_jit_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, + onlygreens=False) annhelper.finish() - def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None, - onlygreens=True): + def _make_hook_graph(self, jitdriver_sd, annhelper, func, + s_result, s_first_arg=None, onlygreens=True): if func is None: return None # @@ -401,38 +430,57 @@ if s_first_arg is not None: extra_args_s.append(s_first_arg) # - args_s = self.portal_args_s + args_s = jitdriver_sd._portal_args_s if onlygreens: - args_s = args_s[:len(self.green_args_spec)] + args_s = args_s[:len(jitdriver_sd._green_args_spec)] graph = annhelper.getgraph(func, extra_args_s + args_s, s_result) funcptr = annhelper.graph2delayed(graph) return funcptr - def make_args_specification(self): - graph, block, index = self.jit_merge_point_pos + def make_args_specifications(self): + for jd in self.jitdrivers_sd: + self.make_args_specification(jd) + + def make_args_specification(self, jd): + graph, block, index = jd._jit_merge_point_pos op = block.operations[index] greens_v, reds_v = support.decode_hp_hint_args(op) ALLARGS = [v.concretetype for v in (greens_v + reds_v)] - self.green_args_spec = [v.concretetype for v in greens_v] - self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] - self.num_green_args = len(self.green_args_spec) + jd._green_args_spec = [v.concretetype for v in greens_v] + jd._red_args_types = [history.getkind(v.concretetype) for v in reds_v] + jd.num_green_args = len(jd._green_args_spec) RESTYPE = graph.getreturnvar().concretetype - (self.JIT_ENTER_FUNCTYPE, - self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) - (self.PORTAL_FUNCTYPE, - self.PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) - (_, self.PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( + (jd._JIT_ENTER_FUNCTYPE, + jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) + (jd._PORTAL_FUNCTYPE, + jd._PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) + (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( [lltype.Signed, llmemory.GCREF], RESTYPE) - def rewrite_can_enter_jit(self): - FUNC = self.JIT_ENTER_FUNCTYPE - FUNCPTR = self.PTR_JIT_ENTER_FUNCTYPE - jit_enter_fnptr = self.helper_func(FUNCPTR, self.maybe_enter_jit_fn) + def rewrite_can_enter_jits(self): + can_enter_jits = find_can_enter_jit(self.translator.graphs) + sublists = {} + for jd in self.jitdrivers_sd: + sublists[jd.jitdriver] = [] + for graph, block, index in can_enter_jits: + op = block.operations[index] + jitdriver = op.args[1].value + assert jitdriver in sublists, \ + "can_enter_jit with no matching jit_merge_point" + sublists[jitdriver].append((graph, block, index)) + for jd in self.jitdrivers_sd: + sublist = sublists[jd.jitdriver] + assert len(sublist) > 0, \ + "found no can_enter_jit for %r" % (jd.jitdriver,) + self.rewrite_can_enter_jit(jd, sublist) + + def rewrite_can_enter_jit(self, jd, can_enter_jits): + FUNC = jd._JIT_ENTER_FUNCTYPE + FUNCPTR = jd._PTR_JIT_ENTER_FUNCTYPE + jit_enter_fnptr = self.helper_func(FUNCPTR, jd._maybe_enter_jit_fn) - graphs = self.translator.graphs - can_enter_jits = find_can_enter_jit(graphs) for graph, block, index in can_enter_jits: - if graph is self.jit_merge_point_pos[0]: + if graph is jd._jit_merge_point_pos[0]: continue op = block.operations[index] @@ -455,7 +503,11 @@ graph = self.annhelper.getgraph(func, args_s, s_result) return self.annhelper.graph2delayed(graph, FUNC) - def rewrite_jit_merge_point(self, policy): + def rewrite_jit_merge_points(self, policy): + for jd in self.jitdrivers_sd: + self.rewrite_jit_merge_point(jd, policy) + + def rewrite_jit_merge_point(self, jd, policy): # # Mutate the original portal graph from this: # @@ -486,9 +538,9 @@ # while 1: # more stuff # - origportalgraph = self.jit_merge_point_pos[0] - portalgraph = self.portal_graph - PORTALFUNC = self.PORTAL_FUNCTYPE + origportalgraph = jd._jit_merge_point_pos[0] + portalgraph = jd.portal_graph + PORTALFUNC = jd._PORTAL_FUNCTYPE # ____________________________________________________________ # Prepare the portal_runner() helper @@ -496,12 +548,12 @@ from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) - self.portal_ptr = portal_ptr + jd._portal_ptr = portal_ptr # portalfunc_ARGS = [] nums = {} for i, ARG in enumerate(PORTALFUNC.ARGS): - if i < len(self.jitdriver.greens): + if i < len(jd.jitdriver.greens): color = 'green' else: color = 'red' @@ -519,7 +571,7 @@ def ll_portal_runner(*args): while 1: try: - self.maybe_enter_from_start_fn(*args) + jd._maybe_enter_from_start_fn(*args) return support.maybe_on_top_of_llinterp(rtyper, portal_ptr)(*args) except self.ContinueRunningNormally, e: @@ -548,16 +600,15 @@ value = cast_base_ptr_to_instance(Exception, value) raise Exception, value - self.ll_portal_runner = ll_portal_runner # for debugging - self.portal_runner_ptr = self.helper_func(self.PTR_PORTAL_FUNCTYPE, - ll_portal_runner) + jd._ll_portal_runner = ll_portal_runner # for debugging + jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE, + ll_portal_runner) self.cpu.portal_calldescr = self.cpu.calldescrof( - self.PTR_PORTAL_FUNCTYPE.TO, - self.PTR_PORTAL_FUNCTYPE.TO.ARGS, - self.PTR_PORTAL_FUNCTYPE.TO.RESULT) - self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) + jd._PTR_PORTAL_FUNCTYPE.TO, + jd._PTR_PORTAL_FUNCTYPE.TO.ARGS, + jd._PTR_PORTAL_FUNCTYPE.TO.RESULT) - vinfo = self.virtualizable_info + vinfo = jd.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -567,6 +618,7 @@ virtualizable = lltype.cast_opaque_ptr( vinfo.VTYPEPTR, virtualizableref) vinfo.reset_vable_token(virtualizable) + XXX # careful here, we must pass the correct jitdriver_sd loop_token = fail_descr.handle_fail(self.metainterp_sd) fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: @@ -596,12 +648,14 @@ value = cast_base_ptr_to_instance(Exception, value) raise Exception, value - self.assembler_call_helper = assembler_call_helper # for debugging + jd._assembler_call_helper = assembler_call_helper # for debugging + # XXX rewrite me, ugly sticking does not work any more self.cpu.assembler_helper_ptr = self.helper_func( - self.PTR_ASSEMBLER_HELPER_FUNCTYPE, + jd._PTR_ASSEMBLER_HELPER_FUNCTYPE, assembler_call_helper) # XXX a bit ugly sticking if vinfo is not None: + XXX # rewrite me, ugly sticking does not work any more self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) self.cpu.vable_token_descr = vinfo.vable_token_descr @@ -612,12 +666,12 @@ # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr # - _, origblock, origindex = self.jit_merge_point_pos + _, origblock, origindex = jd._jit_merge_point_pos op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' greens_v, reds_v = support.decode_hp_hint_args(op) - vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] + vlist = [Constant(jd.portal_runner_ptr, jd._PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v v_result = Variable() @@ -644,8 +698,8 @@ graphs = self.translator.graphs _, PTR_SET_PARAM_FUNCTYPE = self.cpu.ts.get_FuncType([lltype.Signed], lltype.Void) - def make_closure(fullfuncname): - state = self.state + def make_closure(jd, fullfuncname): + state = jd._state def closure(i): getattr(state, fullfuncname)(i) funcptr = self.helper_func(PTR_SET_PARAM_FUNCTYPE, closure) @@ -653,12 +707,17 @@ # for graph, block, i in find_set_param(graphs): op = block.operations[i] - assert op.args[1].value == self.jitdriver + for jd in self.jitdrivers_sd: + if jd.jitdriver is op.args[1].value: + break + else: + assert 0, "jitdriver of set_param() not found" funcname = op.args[2].value - if funcname not in closures: - closures[funcname] = make_closure('set_param_' + funcname) + key = jd, funcname + if key not in closures: + closures[key] = make_closure(jd, 'set_param_' + funcname) op.opname = 'direct_call' - op.args[:3] = [closures[funcname]] + op.args[:3] = [closures[key]] def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Sat Jun 12 09:32:17 2010 @@ -1,7 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.rpython.ootypesystem import ootype -from pypy.rpython.annlowlevel import hlstr, cast_base_ptr_to_instance +from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance from pypy.rpython.annlowlevel import cast_object_to_ptr from pypy.rlib.objectmodel import specialize, we_are_translated, r_dict from pypy.rlib.rarithmetic import intmask @@ -120,6 +120,16 @@ else: assert False +class JitCell(BaseJitCell): + # the counter can mean the following things: + # counter >= 0: not yet traced, wait till threshold is reached + # counter == -1: there is an entry bridge for this cell + # counter == -2: tracing is currently going on for this cell + counter = 0 + compiled_merge_points = None + dont_trace_here = False + entry_loop_token = None + # ____________________________________________________________ @@ -127,9 +137,10 @@ THRESHOLD_LIMIT = sys.maxint // 2 default_jitcell_dict = None - def __init__(self, warmrunnerdesc): + def __init__(self, warmrunnerdesc, jitdriver_sd): "NOT_RPYTHON" self.warmrunnerdesc = warmrunnerdesc + self.jitdriver_sd = jitdriver_sd try: self.profiler = warmrunnerdesc.metainterp_sd.profiler except AttributeError: # for tests @@ -195,8 +206,9 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = self.warmrunnerdesc.virtualizable_info - num_green_args = self.warmrunnerdesc.num_green_args + jitdriver_sd = self.jitdriver_sd + vinfo = jitdriver_sd.virtualizable_info + num_green_args = jitdriver_sd.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() self.make_jitdriver_callbacks() @@ -206,7 +218,6 @@ """Entry point to the JIT. Called at the point with the can_enter_jit() hint. """ - globaldata = metainterp_sd.globaldata if NonConstant(False): # make sure we always see the saner optimizer from an # annotation point of view, otherwise we get lots of @@ -234,11 +245,12 @@ return # bound reached; start tracing from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) # set counter to -2, to mean "tracing in effect" cell.counter = -2 try: - loop_token = metainterp.compile_and_run_once(*args) + loop_token = metainterp.compile_and_run_once(jitdriver_sd, + *args) finally: if cell.counter == -2: cell.counter = 0 @@ -264,7 +276,8 @@ metainterp_sd.profiler.end_running() if vinfo is not None: vinfo.reset_vable_token(virtualizable) - loop_token = fail_descr.handle_fail(metainterp_sd) + loop_token = fail_descr.handle_fail(metainterp_sd, + jitdriver_sd) maybe_compile_and_run._dont_inline_ = True self.maybe_compile_and_run = maybe_compile_and_run @@ -277,8 +290,8 @@ if hasattr(self, 'unwrap_greenkey'): return self.unwrap_greenkey # - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def unwrap_greenkey(greenkey): greenargs = () @@ -302,20 +315,10 @@ if hasattr(self, 'jit_getter'): return self.jit_getter # - class JitCell(BaseJitCell): - # the counter can mean the following things: - # counter >= 0: not yet traced, wait till threshold is reached - # counter == -1: there is an entry bridge for this cell - # counter == -2: tracing is currently going on for this cell - counter = 0 - compiled_merge_points = None - dont_trace_here = False - entry_loop_token = None - # - if self.warmrunnerdesc.get_jitcell_at_ptr is None: - jit_getter = self._make_jitcell_getter_default(JitCell) + if self.jitdriver_sd._get_jitcell_at_ptr is None: + jit_getter = self._make_jitcell_getter_default() else: - jit_getter = self._make_jitcell_getter_custom(JitCell) + jit_getter = self._make_jitcell_getter_custom() # unwrap_greenkey = self.make_unwrap_greenkey() # @@ -327,10 +330,10 @@ # return jit_getter - def _make_jitcell_getter_default(self, JitCell): + def _make_jitcell_getter_default(self): "NOT_RPYTHON" - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def comparekey(greenargs1, greenargs2): i = 0 @@ -361,11 +364,11 @@ return cell return get_jitcell - def _make_jitcell_getter_custom(self, JitCell): + def _make_jitcell_getter_custom(self): "NOT_RPYTHON" rtyper = self.warmrunnerdesc.rtyper - get_jitcell_at_ptr = self.warmrunnerdesc.get_jitcell_at_ptr - set_jitcell_at_ptr = self.warmrunnerdesc.set_jitcell_at_ptr + get_jitcell_at_ptr = self.jitdriver_sd._get_jitcell_at_ptr + set_jitcell_at_ptr = self.jitdriver_sd._set_jitcell_at_ptr lltohlhack = {} # def get_jitcell(*greenargs): @@ -415,9 +418,10 @@ return self.set_future_values warmrunnerdesc = self.warmrunnerdesc + jitdriver_sd = self.jitdriver_sd cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.virtualizable_info - red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) + vinfo = jitdriver_sd.virtualizable_info + red_args_types = unrolling_iterable(jitdriver_sd._red_args_types) # def set_future_values(*redargs): i = 0 @@ -428,8 +432,8 @@ set_future_values_from_vinfo(*redargs) # if vinfo is not None: - i0 = len(warmrunnerdesc.red_args_types) - num_green_args = warmrunnerdesc.num_green_args + i0 = len(jitdriver_sd._red_args_types) + num_green_args = jitdriver_sd.num_green_args vable_static_fields = unrolling_iterable( zip(vinfo.static_extra_types, vinfo.static_fields)) vable_array_fields = unrolling_iterable( @@ -464,7 +468,7 @@ if hasattr(self, 'get_location_str'): return # - can_inline_ptr = self.warmrunnerdesc.can_inline_ptr + can_inline_ptr = self.jitdriver_sd._can_inline_ptr unwrap_greenkey = self.make_unwrap_greenkey() if can_inline_ptr is None: def can_inline_callable(*greenargs): @@ -497,10 +501,15 @@ self.get_assembler_token = get_assembler_token # - get_location_ptr = self.warmrunnerdesc.get_printable_location_ptr + get_location_ptr = self.jitdriver_sd._get_printable_location_ptr if get_location_ptr is None: + missing = '(no jitdriver.get_printable_location!)' + missingll = llstr(missing) def get_location_str(greenkey): - return '(no jitdriver.get_printable_location!)' + if we_are_translated(): + return missingll + else: + return missing else: rtyper = self.warmrunnerdesc.rtyper unwrap_greenkey = self.make_unwrap_greenkey() @@ -514,7 +523,7 @@ return res self.get_location_str = get_location_str # - confirm_enter_jit_ptr = self.warmrunnerdesc.confirm_enter_jit_ptr + confirm_enter_jit_ptr = self.jitdriver_sd._confirm_enter_jit_ptr if confirm_enter_jit_ptr is None: def confirm_enter_jit(*args): return True From arigo at codespeak.net Sat Jun 12 09:32:31 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:32:31 +0200 (CEST) Subject: [pypy-svn] r75301 - pypy/branch/multijit-3 Message-ID: <20100612073231.6CBD6282BF1@codespeak.net> Author: arigo Date: Sat Jun 12 09:32:30 2010 New Revision: 75301 Removed: pypy/branch/multijit-3/ Log: Remove merged branch. From arigo at codespeak.net Sat Jun 12 09:33:24 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:33:24 +0200 (CEST) Subject: [pypy-svn] r75302 - pypy/branch/multijit-4/pypy/jit/codewriter/test Message-ID: <20100612073324.4C3F6282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:33:23 2010 New Revision: 75302 Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py Log: Fix test. Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_codewriter.py Sat Jun 12 09:33:23 2010 @@ -106,7 +106,7 @@ blackholeinterp.setarg_i(0, 6) blackholeinterp.setarg_i(1, 100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 100+6+5+4+3 + assert blackholeinterp.get_tmpreg_i() == 100+6+5+4+3 def test_instantiate(): class A1: id = 651 From arigo at codespeak.net Sat Jun 12 09:37:01 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:37:01 +0200 (CEST) Subject: [pypy-svn] r75303 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612073701.24A95282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:36:59 2010 New Revision: 75303 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_blackhole.py Log: Fix test. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_blackhole.py Sat Jun 12 09:36:59 2010 @@ -42,7 +42,7 @@ blackholeinterp.setarg_i(0, 40) blackholeinterp.setarg_i(1, 2) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_const(): jitcode = JitCode("test") @@ -54,7 +54,7 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(1, 6) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_bigconst(): jitcode = JitCode("test") @@ -66,7 +66,7 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(1, 10000) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_loop(): jitcode = JitCode("test") @@ -85,7 +85,7 @@ blackholeinterp.setarg_i(0x16, 6) # %i0 blackholeinterp.setarg_i(0x17, 100) # %i1 blackholeinterp.run() - assert blackholeinterp.final_result_i() == 100+6+5+4+3 + assert blackholeinterp._final_result_anytype() == 100+6+5+4+3 def test_simple_exception(): jitcode = JitCode("test") @@ -104,12 +104,12 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(0x9, 100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 200 + assert blackholeinterp._final_result_anytype() == 200 # blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(0x9, -100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_convert_and_run_from_pyjitpl(): class MyMIFrame: From arigo at codespeak.net Sat Jun 12 09:38:39 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:38:39 +0200 (CEST) Subject: [pypy-svn] r75304 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612073839.E4C36282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:38:38 2010 New Revision: 75304 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py Log: Fix test. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py Sat Jun 12 09:38:38 2010 @@ -51,14 +51,14 @@ logger_noopt = FakeLogger() logger_ops = FakeLogger() - state = FakeState() stats = Stats() profiler = jitprof.EmptyProfiler() def log(self, msg, event_kind=None): pass class FakeMetaInterp: - pass + class jitdriver_sd: + _state = FakeState() def test_compile_new_loop(): cpu = FakeCPU() From arigo at codespeak.net Sat Jun 12 09:39:13 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 09:39:13 +0200 (CEST) Subject: [pypy-svn] r75305 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612073913.9FFF7282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 09:39:12 2010 New Revision: 75305 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Log: Typo. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Sat Jun 12 09:39:12 2010 @@ -319,7 +319,7 @@ "NOT_RPYTHON" if self._return_type == 'i': return self.get_tmpreg_i() if self._return_type == 'r': return self.get_tmpreg_r() - if self._return_type == 'f': return self.get_tmpreg_v() + if self._return_type == 'f': return self.get_tmpreg_f() if self._return_type == 'v': return None raise ValueError(self._return_type) From arigo at codespeak.net Sat Jun 12 10:01:15 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 10:01:15 +0200 (CEST) Subject: [pypy-svn] r75306 - in pypy/branch/int-between/pypy: jit/metainterp jit/metainterp/test rpython rpython/lltypesystem translator/c/src Message-ID: <20100612080115.85588282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 10:01:13 2010 New Revision: 75306 Modified: pypy/branch/int-between/pypy/jit/metainterp/blackhole.py pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py pypy/branch/int-between/pypy/rpython/normalizecalls.py pypy/branch/int-between/pypy/translator/c/src/int.h Log: Replace the meaning of 'int_between(a,b,c)' from 'a <= b <= c' to the more Pythonic 'a <= b < c'. This also has an advantage: rclass.ll_isinstance() turns into int_between(a,b,a+1) for the case where the class has no subclass. With the new definition this becomes equivalent to 'a==b'. Modified: pypy/branch/int-between/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/blackhole.py Sat Jun 12 10:01:13 2010 @@ -477,7 +477,7 @@ return bool(a) @arguments("i", "i", "i", returns="i") def bhimpl_int_between(a, b, c): - return a <= b <= c + return a <= b < c @arguments("i", "i", returns="i") def bhimpl_uint_lt(a, b): Modified: pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 10:01:13 2010 @@ -319,7 +319,7 @@ def opimpl_int_between(self, b1, b2, b3): b4 = self.execute(rop.INT_SUB, b2, b1) b5 = self.execute(rop.INT_SUB, b3, b1) - return self.execute(rop.UINT_LE, b4, b5) + return self.execute(rop.UINT_LT, b4, b5) @arguments("box", "descr", "orgpc") def opimpl_switch(self, valuebox, switchdict, orgpc): Modified: pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 10:01:13 2010 @@ -581,30 +581,30 @@ assert res == expect_result self.check_operations_history(expect_operations) # - check('n', 'm', 'p', True, int_sub=2, uint_le=1) - check('n', 'p', 'm', False, int_sub=2, uint_le=1) + check('n', 'm', 'p', True, int_sub=2, uint_lt=1) + check('n', 'p', 'm', False, int_sub=2, uint_lt=1) # - check('n', 'm', 6, True, int_sub=2, uint_le=1) + check('n', 'm', 6, False, int_sub=2, uint_lt=1) # - check('n', 4, 'p', False, int_sub=2, uint_le=1) - check('n', 5, 'p', True, int_sub=2, uint_le=1) - check('n', 8, 'p', False, int_sub=2, uint_le=1) + check('n', 4, 'p', False, int_sub=2, uint_lt=1) + check('n', 5, 'p', True, int_sub=2, uint_lt=1) + check('n', 8, 'p', False, int_sub=2, uint_lt=1) # - check('n', 6, 7, True, int_sub=2, uint_le=1) + check('n', 6, 7, True, int_sub=2, uint_lt=1) # - check(-2, 'n', 'p', True, int_sub=2, uint_le=1) - check(-2, 'm', 'p', True, int_sub=2, uint_le=1) - check(-2, 'p', 'm', False, int_sub=2, uint_le=1) - #check(0, 'n', 'p', True, uint_le=1) xxx implement me - #check(0, 'm', 'p', True, uint_le=1) - #check(0, 'p', 'm', False, uint_le=1) + check(-2, 'n', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'm', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'p', 'm', False, int_sub=2, uint_lt=1) + #check(0, 'n', 'p', True, uint_lt=1) xxx implement me + #check(0, 'm', 'p', True, uint_lt=1) + #check(0, 'p', 'm', False, uint_lt=1) # - check(2, 'n', 6, True, int_sub=1, uint_le=1) - check(2, 'm', 6, True, int_sub=1, uint_le=1) - check(2, 'p', 6, False, int_sub=1, uint_le=1) + check(2, 'n', 6, True, int_sub=1, uint_lt=1) + check(2, 'm', 6, False, int_sub=1, uint_lt=1) + check(2, 'p', 6, False, int_sub=1, uint_lt=1) # - check(2, 6, 'n', False, int_sub=1, uint_le=1) - check(2, 6, 'm', True, int_sub=1, uint_le=1) + check(2, 6, 'm', False, int_sub=1, uint_lt=1) + check(2, 6, 'p', True, int_sub=1, uint_lt=1) # check(2, 40, 6, False) check(2, 40, 60, True) Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/int-between/pypy/rpython/lltypesystem/lloperation.py Sat Jun 12 10:01:13 2010 @@ -227,7 +227,7 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), - 'int_between': LLOp(canfold=True), # a <= b <= c + 'int_between': LLOp(canfold=True), # a <= b < c 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), Modified: pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/int-between/pypy/rpython/lltypesystem/opimpl.py Sat Jun 12 10:01:13 2010 @@ -201,7 +201,7 @@ assert lltype.typeOf(a) is lltype.Signed assert lltype.typeOf(b) is lltype.Signed assert lltype.typeOf(c) is lltype.Signed - return a <= b <= c + return a <= b < c def op_int_and(x, y): if not isinstance(x, int): Modified: pypy/branch/int-between/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/branch/int-between/pypy/rpython/normalizecalls.py (original) +++ pypy/branch/int-between/pypy/rpython/normalizecalls.py Sat Jun 12 10:01:13 2010 @@ -292,7 +292,7 @@ else: return cmp(self.orderwitness, other.orderwitness) - # support for implementing int_between: (a<=b<=c) with (b-a<=c-a) + # support for implementing int_between: (a<=b Author: arigo Date: Sat Jun 12 10:11:36 2010 New Revision: 75307 Modified: pypy/branch/int-between/pypy/translator/c/funcgen.py Log: Optimize the common case of int_between(a, n, a+1). Modified: pypy/branch/int-between/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/int-between/pypy/translator/c/funcgen.py (original) +++ pypy/branch/int-between/pypy/translator/c/funcgen.py Sat Jun 12 10:11:36 2010 @@ -318,6 +318,7 @@ def gen_op(self, op): macro = 'OP_%s' % op.opname.upper() + line = None if op.opname.startswith('gc_'): meth = getattr(self.gcpolicy, macro, None) if meth: @@ -326,7 +327,7 @@ meth = getattr(self, macro, None) if meth: line = meth(op) - if meth is None: + if line is None: lst = [self.expr(v) for v in op.args] lst.append(self.expr(op.result)) line = '%s(%s);' % (macro, ', '.join(lst)) @@ -849,5 +850,16 @@ return 'PYPY_DEBUG_CATCH_EXCEPTION("%s", %s, %s);' % ( self.getdebugfunctionname(), gottype, ' || '.join(exprs)) + def OP_INT_BETWEEN(self, op): + if (isinstance(op.args[0], Constant) and + isinstance(op.args[2], Constant) and + op.args[2].value - op.args[0].value == 1): + # (a <= b < a+1) ----> (b == a) + return '%s = (%s == %s); /* was INT_BETWEEN */' % ( + self.expr(op.result), + self.expr(op.args[1]), + self.expr(op.args[0])) + else: + return None # use the default assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) From arigo at codespeak.net Sat Jun 12 10:13:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 10:13:50 +0200 (CEST) Subject: [pypy-svn] r75308 - in pypy/branch/int-between/pypy/jit/metainterp: . test Message-ID: <20100612081350.2E025282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 10:13:48 2010 New Revision: 75308 Modified: pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Log: Implement the common case of int_betwen(a, b, a+1) in pyjitpl too. Modified: pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 10:13:48 2010 @@ -317,9 +317,13 @@ @arguments("box", "box", "box") def opimpl_int_between(self, b1, b2, b3): - b4 = self.execute(rop.INT_SUB, b2, b1) b5 = self.execute(rop.INT_SUB, b3, b1) - return self.execute(rop.UINT_LT, b4, b5) + if isinstance(b5, ConstInt) and b5.getint() == 1: + # the common case of int_between(a, b, a+1) turns into just INT_EQ + return self.execute(rop.INT_EQ, b2, b1) + else: + b4 = self.execute(rop.INT_SUB, b2, b1) + return self.execute(rop.UINT_LT, b4, b5) @arguments("box", "descr", "orgpc") def opimpl_switch(self, valuebox, switchdict, orgpc): Modified: pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/int-between/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 10:13:48 2010 @@ -602,6 +602,8 @@ check(2, 'n', 6, True, int_sub=1, uint_lt=1) check(2, 'm', 6, False, int_sub=1, uint_lt=1) check(2, 'p', 6, False, int_sub=1, uint_lt=1) + check(5, 'n', 6, True, int_eq=1) # 6 == 5+1 + check(5, 'm', 6, False, int_eq=1) # 6 == 5+1 # check(2, 6, 'm', False, int_sub=1, uint_lt=1) check(2, 6, 'p', True, int_sub=1, uint_lt=1) From arigo at codespeak.net Sat Jun 12 10:30:05 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 10:30:05 +0200 (CEST) Subject: [pypy-svn] r75309 - in pypy/branch/multijit-4/pypy/jit: codewriter metainterp metainterp/test Message-ID: <20100612083005.D3A6C282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 10:30:03 2010 New Revision: 75309 Modified: pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-4/pypy/jit/metainterp/compile.py pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Log: Fix bugs. Modified: pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py Sat Jun 12 10:30:03 2010 @@ -326,7 +326,8 @@ def handle_recursive_call(self, op): jitdriver_sd = self.callcontrol.jitdriver_sd_from_portal_runner_ptr( - op.args[0]) + op.args[0].value) + assert jitdriver_sd is not None ops = self.promote_greens(op.args[1:], jitdriver_sd.jitdriver) num_green_args = len(jitdriver_sd.jitdriver.greens) args = ([Constant(jitdriver_sd.index, lltype.Signed)] + Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Sat Jun 12 10:30:03 2010 @@ -775,24 +775,23 @@ # call the interpreter main loop from here, and just return its # result. sd = self.builder.metainterp_sd - xxxxxxxxxxxx - if sd.result_type == 'void': + result_type = sd.jitdrivers_sd[jdindex].result_type + if result_type == 'v': self.bhimpl_recursive_call_v(jdindex, *args) self.bhimpl_void_return() - elif sd.result_type == 'int': + elif result_type == 'i': x = self.bhimpl_recursive_call_i(jdindex, *args) self.bhimpl_int_return(x) - elif sd.result_type == 'ref': + elif result_type == 'r': x = self.bhimpl_recursive_call_r(jdindex, *args) self.bhimpl_ref_return(x) - elif sd.result_type == 'float': + elif result_type == 'f': x = self.bhimpl_recursive_call_f(jdindex, *args) self.bhimpl_float_return(x) assert False def get_portal_runner(self, jdindex): - metainterp_sd = self.builder.metainterp_sd - jitdriver_sd = metainterp_sd.jitdrivers_sd[jdindex] + jitdriver_sd = self.builder.metainterp_sd.jitdrivers_sd[jdindex] fnptr = llmemory.cast_ptr_to_adr(jitdriver_sd.portal_runner_ptr) fnptr = heaptracker.adr2int(fnptr) calldescr = jitdriver_sd.mainjitcode.calldescr Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/compile.py Sat Jun 12 10:30:03 2010 @@ -68,7 +68,7 @@ loop.token = loop_token loop.operations[-1].descr = loop_token # patch the target of the JUMP try: - old_loop_token = jitdriver_sd._state.optimize_loop( + old_loop_token = jitdriver_sd.warmstate.optimize_loop( metainterp_sd, old_loop_tokens, loop) except InvalidLoop: return None @@ -279,7 +279,7 @@ _trace_and_compile_from_bridge._dont_inline_ = True def must_compile(self, metainterp_sd, jitdriver_sd): - trace_eagerness = jitdriver_sd._state.trace_eagerness + trace_eagerness = jitdriver_sd.warmstate.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness @@ -478,7 +478,7 @@ new_loop.token = new_loop_token send_loop_to_backend(metainterp_sd, new_loop, "entry bridge") # send the new_loop to warmspot.py, to be called directly the next time - jitdriver_sd._state.attach_unoptimized_bridge_from_interp( + jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp( self.original_greenkey, new_loop_token) # store the new loop in compiled_merge_points too @@ -506,11 +506,11 @@ # clone ops, as optimize_bridge can mutate the ops new_loop.operations = [op.clone() for op in metainterp.history.operations] metainterp_sd = metainterp.staticdata - jitdriver_sd = metainterp.jitdriver_sd + state = metainterp.jitdriver_sd.warmstate try: - target_loop_token = jitdriver_sd._state.optimize_bridge(metainterp_sd, - old_loop_tokens, - new_loop) + target_loop_token = state.optimize_bridge(metainterp_sd, + old_loop_tokens, + new_loop) except InvalidLoop: # XXX I am fairly convinced that optimize_bridge cannot actually raise # InvalidLoop Modified: pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py Sat Jun 12 10:30:03 2010 @@ -10,6 +10,7 @@ # self.num_green_args ... pypy.jit.metainterp.warmspot # self.result_type ... pypy.jit.metainterp.warmspot # self.virtualizable_info... pypy.jit.metainterp.warmspot + # self.warmstate ... pypy.jit.metainterp.warmspot # self.index ... pypy.jit.codewriter.call # self.mainjitcode ... pypy.jit.codewriter.call Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 10:30:03 2010 @@ -659,11 +659,10 @@ @arguments("int", "boxes3", "boxes3") def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes - metainterp_sd = self.metainterp.staticdata - xxxx - portal_code = metainterp_sd.portal_code - warmrunnerstate = metainterp_sd.state + portal_code = targetjitdriver_sd.mainjitcode + warmrunnerstate = targetjitdriver_sd.warmstate token = None if warmrunnerstate.inlining: if warmrunnerstate.can_inline_callable(greenboxes): @@ -672,12 +671,13 @@ token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - self.verify_green_args(greenboxes) + self.verify_green_args(targetjitdriver_sd, greenboxes) # - k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + k = llmemory.cast_ptr_to_adr(targetjitdriver_sd.portal_runner_ptr) funcbox = ConstInt(heaptracker.adr2int(k)) return self.do_residual_call(funcbox, portal_code.calldescr, - allboxes, assembler_call_token=token) + allboxes, assembler_call_token=token, + assembler_call_jd=targetjitdriver_sd) opimpl_recursive_call_i = _opimpl_recursive_call opimpl_recursive_call_r = _opimpl_recursive_call @@ -768,18 +768,18 @@ raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - def verify_green_args(self, jdindex, varargs): - jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] - num_green_args = jitdriver.num_green_args + def verify_green_args(self, jitdriver_sd, varargs): + num_green_args = jitdriver_sd.num_green_args assert len(varargs) == num_green_args for i in range(num_green_args): assert isinstance(varargs[i], Const) @arguments("orgpc", "int", "boxes3", "boxes3") def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes): - self.verify_green_args(jdindex, greenboxes) + jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] + self.verify_green_args(jitdriver_sd, greenboxes) # xxx we may disable the following line in some context later - self.debug_merge_point(jdindex, greenboxes) + self.debug_merge_point(jitdriver_sd, greenboxes) if self.metainterp.seen_can_enter_jit: self.metainterp.seen_can_enter_jit = False # Assert that it's impossible to arrive here with in_recursion @@ -787,7 +787,7 @@ # to True by opimpl_can_enter_jit, which should be executed # just before opimpl_jit_merge_point (no recursion inbetween). assert not self.metainterp.in_recursion - assert jdindex == self.metainterp.jitdriver_sd.index + assert jitdriver_sd is self.metainterp.jitdriver_sd # Set self.pc to point to jit_merge_point instead of just after: # if reached_can_enter_jit() raises SwitchToBlackhole, then the # pc is still at the jit_merge_point, which is a point that is @@ -797,10 +797,9 @@ self.metainterp.reached_can_enter_jit(greenboxes, redboxes) self.pc = saved_pc - def debug_merge_point(self, jdindex, greenkey): + def debug_merge_point(self, jitdriver_sd, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - jitdriver = self.metainterp.staticdata.jitdrivers_sd[jdindex] - loc = jitdriver._state.get_location_str(greenkey) + loc = jitdriver_sd.warmstate.get_location_str(greenkey) debug_print(loc) constloc = self.metainterp.cpu.ts.conststr(loc) self.metainterp.history.record(rop.DEBUG_MERGE_POINT, @@ -1002,7 +1001,8 @@ return resbox def do_residual_call(self, funcbox, descr, argboxes, - assembler_call_token=None): + assembler_call_token=None, + assembler_call_jd=None): # First build allboxes: it may need some reordering from the # list provided in argboxes, depending on the order in which # the arguments are expected by the function @@ -1047,7 +1047,8 @@ rop.CALL_MAY_FORCE, allboxes, descr=descr) self.metainterp.vrefs_after_residual_call() if assembler_call_token is not None: - self.metainterp.direct_assembler_call(assembler_call_token) + self.metainterp.direct_assembler_call(assembler_call_token, + assembler_call_jd) if resbox is not None: self.make_result_of_lastop(resbox) self.metainterp.vable_after_residual_call() @@ -1135,7 +1136,7 @@ def setup_jitdrivers_sd(self, optimizer): if optimizer is not None: for jd in self.jitdrivers_sd: - jd._state.set_param_optimizer(optimizer) + jd.warmstate.set_param_optimizer(optimizer) def finish_setup(self, codewriter, optimizer=None): from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder @@ -1468,7 +1469,7 @@ self.resumekey.reset_counter_from_failure() def blackhole_if_trace_too_long(self): - warmrunnerstate = self.jitdriver_sd._state + warmrunnerstate = self.jitdriver_sd.warmstate if len(self.history.operations) > warmrunnerstate.trace_limit: greenkey_of_huge_function = self.find_biggest_function() self.portal_trace_positions = None @@ -1678,7 +1679,7 @@ raise NotImplementedError(opname[opnum]) def get_compiled_merge_points(self, greenkey): - cell = self.jitdriver_sd._state.jit_cell_at_key(greenkey) + cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey) if cell.compiled_merge_points is None: cell.compiled_merge_points = [] return cell.compiled_merge_points @@ -1975,8 +1976,7 @@ abox, ConstInt(j), itembox) assert i + 1 == len(self.virtualizable_boxes) - def gen_load_from_other_virtualizable(self, vbox): - vinfo = self.jitdriver_sd.virtualizable_info + def gen_load_from_other_virtualizable(self, vinfo, vbox): boxes = [] assert vinfo is not None for i in range(vinfo.num_static_extra_boxes): @@ -2048,19 +2048,19 @@ op.args = [resbox_as_const] + op.args return resbox - def direct_assembler_call(self, token): + def direct_assembler_call(self, token, targetjitdriver_sd): """ Generate a direct call to assembler for portal entry point, patching the CALL_MAY_FORCE that occurred just now. """ op = self.history.operations.pop() assert op.opnum == rop.CALL_MAY_FORCE - num_green_args = self.staticdata.num_green_args + num_green_args = targetjitdriver_sd.num_green_args args = op.args[num_green_args + 1:] - vinfo = self.jitdriver_sd.virtualizable_info + vinfo = targetjitdriver_sd.virtualizable_info if vinfo is not None: vindex = vinfo.index_of_virtualizable vbox = args[vindex - num_green_args] - args = args + self.gen_load_from_other_virtualizable(vbox) + args = args + self.gen_load_from_other_virtualizable(vinfo, vbox) # ^^^ and not "+=", which makes 'args' a resizable list op.opnum = rop.CALL_ASSEMBLER op.args = args Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 10:30:03 2010 @@ -53,8 +53,9 @@ testself.cw = cw cw.find_all_graphs(JitPolicy()) # - testself.warmrunnerstate = FakeJitDriverSD._state = FakeWarmRunnerState() + testself.warmrunnerstate = FakeWarmRunnerState() testself.warmrunnerstate.cpu = cpu + FakeJitDriverSD.warmstate = testself.warmrunnerstate if hasattr(testself, 'finish_setup_for_interp_operations'): testself.finish_setup_for_interp_operations() # @@ -831,7 +832,7 @@ translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=self.CPUClass) - state = warmrunnerdesc.jitdrivers_sd[0]._state + state = warmrunnerdesc.jitdrivers_sd[0].warmstate state.set_param_threshold(3) # for tests state.set_param_trace_eagerness(0) # for tests warmrunnerdesc.finish() Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_compile.py Sat Jun 12 10:30:03 2010 @@ -58,7 +58,7 @@ class FakeMetaInterp: class jitdriver_sd: - _state = FakeState() + warmstate = FakeState() def test_compile_new_loop(): cpu = FakeCPU() Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 10:30:03 2010 @@ -71,11 +71,11 @@ translator.config.translation.list_comprehension_operations = True warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds) for jd in warmrunnerdesc.jitdrivers_sd: - jd._state.set_param_threshold(3) # for tests - jd._state.set_param_trace_eagerness(2) # for tests - jd._state.set_param_trace_limit(trace_limit) - jd._state.set_param_inlining(inline) - jd._state.set_param_debug(debug_level) + jd.warmstate.set_param_threshold(3) # for tests + jd.warmstate.set_param_trace_eagerness(2) # for tests + jd.warmstate.set_param_trace_limit(trace_limit) + jd.warmstate.set_param_inlining(inline) + jd.warmstate.set_param_debug(debug_level) warmrunnerdesc.finish() res = interp.eval_graph(graph, args) if not kwds.get('translate_support_code', False): @@ -361,7 +361,7 @@ from pypy.jit.metainterp.warmstate import WarmEnterState state = WarmEnterState(self, jd) maybe_compile_and_run = state.make_entry_point() - jd._state = state + jd.warmstate = state def crash_in_jit(e): if not we_are_translated(): @@ -699,7 +699,7 @@ _, PTR_SET_PARAM_FUNCTYPE = self.cpu.ts.get_FuncType([lltype.Signed], lltype.Void) def make_closure(jd, fullfuncname): - state = jd._state + state = jd.warmstate def closure(i): getattr(state, fullfuncname)(i) funcptr = self.helper_func(PTR_SET_PARAM_FUNCTYPE, closure) Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Sat Jun 12 10:30:03 2010 @@ -187,8 +187,7 @@ cell = self.jit_cell_at_key(greenkey) cell.dont_trace_here = True debug_start("jit-disableinlining") - sd = self.warmrunnerdesc.metainterp_sd - loc = sd.state.get_location_str(greenkey) + loc = self.get_location_str(greenkey) debug_print("disabled inlining", loc) debug_stop("jit-disableinlining") From arigo at codespeak.net Sat Jun 12 10:40:00 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 10:40:00 +0200 (CEST) Subject: [pypy-svn] r75310 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612084000.6CBF1282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 10:39:59 2010 New Revision: 75310 Added: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Log: Add a first simple test about multiple jitdrivers. Added: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py ============================================================================== --- (empty file) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Sat Jun 12 10:39:59 2010 @@ -0,0 +1,34 @@ +"""Tests for multiple JitDrivers.""" +from pypy.rlib.jit import JitDriver +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin + + +class MultipleJitDriversTests: + + def test_simple(self): + myjitdriver1 = JitDriver(greens=[], reds=['n', 'm']) + myjitdriver2 = JitDriver(greens=['g'], reds=['r']) + # + def loop1(n, m): + while n > 0: + myjitdriver1.can_enter_jit(n=n, m=m) + myjitdriver1.jit_merge_point(n=n, m=m) + n -= m + return n + # + def loop2(g, r): + while r > 0: + myjitdriver2.can_enter_jit(g=g, r=r) + myjitdriver2.jit_merge_point(g=g, r=r) + r += loop1(r, g) - 1 + return r + # + res = self.meta_interp(loop2, [4, 40]) + assert res == loop2(4, 40) + + +class TestLLtype(MultipleJitDriversTests, LLJitMixin): + pass + +class TestOOtype(MultipleJitDriversTests, OOJitMixin): + pass From arigo at codespeak.net Sat Jun 12 11:02:49 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 11:02:49 +0200 (CEST) Subject: [pypy-svn] r75311 - in pypy/branch/multijit-4/pypy/jit: codewriter codewriter/test metainterp metainterp/test Message-ID: <20100612090249.A7CDE282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 11:02:46 2010 New Revision: 75311 Modified: pypy/branch/multijit-4/pypy/jit/codewriter/call.py pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Log: Add a test (by adding an assert in pyjitpl's opimpl_can_enter_jit). Fix. Modified: pypy/branch/multijit-4/pypy/jit/codewriter/call.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/call.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/call.py Sat Jun 12 11:02:46 2010 @@ -259,6 +259,12 @@ return jd return None + def jitdriver_sd_from_jitdriver(self, jitdriver): + for jd in self.jitdrivers_sd: + if jd.jitdriver is jitdriver: + return jd + return None + def get_vinfo(self, VTYPEPTR): seen = set() for jd in self.jitdrivers_sd: Modified: pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/jtransform.py Sat Jun 12 11:02:46 2010 @@ -787,7 +787,10 @@ return ops + [op1] def handle_jit_marker__can_enter_jit(self, op, jitdriver): - return SpaceOperation('can_enter_jit', [], None) + jd = self.callcontrol.jitdriver_sd_from_jitdriver(jitdriver) + assert jd is not None + c_index = Constant(jd.index, lltype.Signed) + return SpaceOperation('can_enter_jit', [c_index], None) def rewrite_op_debug_assert(self, op): log.WARNING("found debug_assert in %r; should have be removed" % Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_flatten.py Sat Jun 12 11:02:46 2010 @@ -584,13 +584,18 @@ class FakeJitDriverSD: jitdriver = myjitdriver index = 27 + jd = FakeJitDriverSD() + class MyFakeCallControl(FakeCallControl): + def jitdriver_sd_from_jitdriver(self, jitdriver): + assert jitdriver == myjitdriver + return jd self.encoding_test(f, [4, 5], """ -live- %i0, %i1 int_guard_value %i0 jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[] - can_enter_jit + can_enter_jit $27 void_return - """, transform=True, liveness=True, jd=FakeJitDriverSD()) + """, transform=True, liveness=True, cc=MyFakeCallControl(), jd=jd) def test_keepalive(self): S = lltype.GcStruct('S') Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Sat Jun 12 11:02:46 2010 @@ -756,8 +756,8 @@ # ---------- # the main hints and recursive calls - @arguments() - def bhimpl_can_enter_jit(): + @arguments("i") + def bhimpl_can_enter_jit(jdindex): pass @arguments("self", "i", "I", "R", "F", "I", "R", "F") Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 11:02:46 2010 @@ -761,11 +761,13 @@ self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) return clsbox - @arguments() - def opimpl_can_enter_jit(self): + @arguments("int") + def opimpl_can_enter_jit(self, jdindex): if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() + assert jdindex == self.metainterp.jitdriver_sd.index, ( + "found a can_enter_jit that does not match the current jitdriver") self.metainterp.seen_can_enter_jit = True def verify_green_args(self, jitdriver_sd, varargs): Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Sat Jun 12 11:02:46 2010 @@ -23,7 +23,7 @@ r += loop1(r, g) - 1 return r # - res = self.meta_interp(loop2, [4, 40]) + res = self.meta_interp(loop2, [4, 40], repeat=7) assert res == loop2(4, 40) Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 11:02:46 2010 @@ -681,6 +681,18 @@ origblock.operations.append(newop) origblock.exitswitch = None origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) + # + # Also kill any can_enter_jit left behind (example: see + # test_jitdriver.test_simple, which has a can_enter_jit in + # loop1's origportalgraph) + can_enter_jits = _find_jit_marker([origportalgraph], 'can_enter_jit') + for _, block, i in can_enter_jits: + op = block.operations[i] + assert op.opname == 'jit_marker' + block.operations[i] = SpaceOperation('same_as', + [Constant(None, lltype.Void)], + op.result) + # checkgraph(origportalgraph) def add_finish(self): From arigo at codespeak.net Sat Jun 12 11:12:32 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 11:12:32 +0200 (CEST) Subject: [pypy-svn] r75312 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612091232.A4481282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 11:12:31 2010 New Revision: 75312 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Log: Took me a little while to figure out that CALL_ASSEMBLER is only generated if we pass inline=True -- and then have a function can_inline that always return False in this case... Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Sat Jun 12 11:12:31 2010 @@ -6,7 +6,8 @@ class MultipleJitDriversTests: def test_simple(self): - myjitdriver1 = JitDriver(greens=[], reds=['n', 'm']) + myjitdriver1 = JitDriver(greens=[], reds=['n', 'm'], + can_inline = lambda *args: False) myjitdriver2 = JitDriver(greens=['g'], reds=['r']) # def loop1(n, m): @@ -23,7 +24,7 @@ r += loop1(r, g) - 1 return r # - res = self.meta_interp(loop2, [4, 40], repeat=7) + res = self.meta_interp(loop2, [4, 40], repeat=7, inline=True) assert res == loop2(4, 40) From arigo at codespeak.net Sat Jun 12 11:52:54 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 11:52:54 +0200 (CEST) Subject: [pypy-svn] r75316 - in pypy/branch/multijit-4/pypy/jit/backend: . llgraph test Message-ID: <20100612095254.ACD87282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 11:52:52 2010 New Revision: 75316 Modified: pypy/branch/multijit-4/pypy/jit/backend/llgraph/llimpl.py pypy/branch/multijit-4/pypy/jit/backend/model.py pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py Log: Change the interface: now CALL_ASSEMBLER's descr, which is a LoopToken, must also contain an 'outermost_jitdriver_sd' with the few attributes needed by the backend to do the call. This replaces sticking the attributes on the cpu, which no longer works in this branch. Modified: pypy/branch/multijit-4/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/llgraph/llimpl.py Sat Jun 12 11:52:52 2010 @@ -833,13 +833,16 @@ raise Exception("Nonsense type %s" % TYPE) failindex = self.cpu._execute_token(loop_token) + jd = loop_token.outermost_jitdriver_sd + assert jd is not None, ("call_assembler(): the loop_token needs " + "to have 'outermost_jitdriver_sd'") + if jd.index_of_virtualizable != -1: + vable = args[jd.index_of_virtualizable] + else: + vable = lltype.nullptr(llmemory.GCREF.TO) + assembler_helper_ptr = jd.assembler_helper_adr.ptr # fish try: - if self.cpu.index_of_virtualizable != -1: - return self.cpu.assembler_helper_ptr(failindex, - args[self.cpu.index_of_virtualizable]) - else: - return self.cpu.assembler_helper_ptr(failindex, - lltype.nullptr(llmemory.GCREF.TO)) + return assembler_helper_ptr(failindex, vable) except LLException, lle: assert _last_exception is None, "exception left behind" _last_exception = lle Modified: pypy/branch/multijit-4/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/model.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/model.py Sat Jun 12 11:52:52 2010 @@ -3,10 +3,6 @@ class AbstractCPU(object): supports_floats = False - _got_exception = None - # assembler_helper_ptr - a pointer to helper to call after a direct - # assembler call - portal_calldescr = None done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 done_with_this_frame_ref_v = -1 Modified: pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py Sat Jun 12 11:52:52 2010 @@ -1698,16 +1698,23 @@ assert self.cpu.get_latest_value_int(0) == 10 called.append(failindex) return 4 + 9 - self.cpu.index_of_virtualizable = -1 - self.cpu.assembler_helper_ptr = llhelper(lltype.Ptr(lltype.FuncType - ([lltype.Signed, llmemory.GCREF], lltype.Signed)), assembler_helper) - + + FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF], + lltype.Signed)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + vable_token_descr = None + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + ops = ''' [i0, i1] i2 = int_add(i0, i1) finish(i2)''' loop = parse(ops) looptoken = LoopToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) ARGS = [lltype.Signed, lltype.Signed] RES = lltype.Signed @@ -1739,9 +1746,16 @@ assert self.cpu.get_latest_value_float(0) == 1.2 + 3.2 called.append(failindex) return 13.5 - self.cpu.index_of_virtualizable = -1 - self.cpu.assembler_helper_ptr = llhelper(lltype.Ptr(lltype.FuncType - ([lltype.Signed, llmemory.GCREF], lltype.Float)), assembler_helper) + + FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF], + lltype.Float)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + vable_token_descr = None + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + ARGS = [lltype.Float, lltype.Float] RES = lltype.Float self.cpu.portal_calldescr = self.cpu.calldescrof( @@ -1753,6 +1767,7 @@ finish(f2)''' loop = parse(ops) looptoken = LoopToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) self.cpu.set_future_value_float(0, 1.2) self.cpu.set_future_value_float(1, 2.3) From arigo at codespeak.net Sat Jun 12 12:01:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:01:44 +0200 (CEST) Subject: [pypy-svn] r75318 - in pypy/branch/multijit-4/pypy/jit/backend: test x86 Message-ID: <20100612100144.19F03282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:01:42 2010 New Revision: 75318 Modified: pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py pypy/branch/multijit-4/pypy/jit/backend/x86/assembler.py pypy/branch/multijit-4/pypy/jit/backend/x86/regalloc.py Log: Fix the x86 backend. Modified: pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/test/runner_test.py Sat Jun 12 12:01:42 2010 @@ -1703,7 +1703,6 @@ lltype.Signed)) class FakeJitDriverSD: index_of_virtualizable = -1 - vable_token_descr = None _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) assembler_helper_adr = llmemory.cast_ptr_to_adr( _assembler_helper_ptr) @@ -1751,7 +1750,6 @@ lltype.Float)) class FakeJitDriverSD: index_of_virtualizable = -1 - vable_token_descr = None _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) assembler_helper_adr = llmemory.cast_ptr_to_adr( _assembler_helper_ptr) Modified: pypy/branch/multijit-4/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/x86/assembler.py Sat Jun 12 12:01:42 2010 @@ -109,7 +109,6 @@ self.malloc_array_func_addr = 0 self.malloc_str_func_addr = 0 self.malloc_unicode_func_addr = 0 - self.assembler_helper_adr = 0 self.fail_boxes_int = values_array(lltype.Signed, failargs_limit) self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit) self.fail_boxes_float = values_array(lltype.Float, failargs_limit) @@ -144,14 +143,6 @@ ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode() self.malloc_unicode_func_addr = rffi.cast(lltype.Signed, ll_new_unicode) - if we_are_translated(): - self.assembler_helper_adr = self.cpu.cast_ptr_to_int( - self.cpu.assembler_helper_ptr) - else: - if getattr(self.cpu, 'assembler_helper_ptr', None): - self.assembler_helper_adr = self.cpu.cast_ptr_to_int( - self.cpu.assembler_helper_ptr) - # done # we generate the loop body in 'mc' # 'mc2' is for guard recovery code @@ -1389,7 +1380,10 @@ je_location = mc.get_relative_pos() # # Path A: use assembler_helper_adr - self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, + jd = descr.outermost_jitdriver_sd + assert jd is not None + asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr) + self._emit_call(rel32(asm_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) if isinstance(result_loc, MODRM64): mc.FSTP(result_loc) @@ -1403,9 +1397,9 @@ mc.overwrite(je_location - 1, [chr(offset)]) # # Reset the vable token --- XXX really too much special logic here:-( - if self.cpu.index_of_virtualizable >= 0: + if jd.index_of_virtualizable >= 0: from pypy.jit.backend.llsupport.descr import BaseFieldDescr - fielddescr = self.cpu.vable_token_descr + fielddescr = jd.vable_token_descr assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset mc.MOV(eax, arglocs[1]) Modified: pypy/branch/multijit-4/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/multijit-4/pypy/jit/backend/x86/regalloc.py Sat Jun 12 12:01:42 2010 @@ -636,10 +636,14 @@ self._consider_call(op, guard_op) def consider_call_assembler(self, op, guard_op): - descr = op.descr portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) - vable_index = self.assembler.cpu.index_of_virtualizable + # + descr = op.descr + assert isinstance(descr, LoopToken) + jd = descr.outermost_jitdriver_sd + assert jd is not None + vable_index = jd.index_of_virtualizable if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) From arigo at codespeak.net Sat Jun 12 12:02:55 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:02:55 +0200 (CEST) Subject: [pypy-svn] r75319 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612100255.00DCB282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:02:54 2010 New Revision: 75319 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py pypy/branch/multijit-4/pypy/jit/metainterp/history.py pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Log: Fix the front-end. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/compile.py Sat Jun 12 12:02:54 2010 @@ -39,9 +39,10 @@ name = metainterp.staticdata.stats.name_for_new_loop() return TreeLoop(name) -def make_loop_token(nb_args): +def make_loop_token(nb_args, jitdriver_sd): loop_token = LoopToken() loop_token.specnodes = [prebuiltNotSpecNode] * nb_args + loop_token.outermost_jitdriver_sd = jitdriver_sd return loop_token # ____________________________________________________________ @@ -64,7 +65,7 @@ loop.operations = [op.clone() for op in ops] metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd - loop_token = make_loop_token(len(loop.inputargs)) + loop_token = make_loop_token(len(loop.inputargs), jitdriver_sd) loop.token = loop_token loop.operations[-1].descr = loop_token # patch the target of the JUMP try: @@ -472,7 +473,7 @@ metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd metainterp.history.inputargs = self.redkey - new_loop_token = make_loop_token(len(self.redkey)) + new_loop_token = make_loop_token(len(self.redkey), jitdriver_sd) new_loop.greenkey = self.original_greenkey new_loop.inputargs = self.redkey new_loop.token = new_loop_token Modified: pypy/branch/multijit-4/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/history.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/history.py Sat Jun 12 12:02:54 2010 @@ -694,6 +694,7 @@ generated assembler. """ terminating = False # see TerminatingLoopToken in compile.py + outermost_jitdriver_sd = None # specnodes = ... # and more data specified by the backend when the loop is compiled number = 0 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py Sat Jun 12 12:02:54 2010 @@ -14,6 +14,11 @@ # self.index ... pypy.jit.codewriter.call # self.mainjitcode ... pypy.jit.codewriter.call + # These attributes are read by the backend in CALL_ASSEMBLER: + # self.assembler_helper_adr + # self.index_of_virtualizable + # self.vable_token_descr + # warmspot sets extra attributes starting with '_' for its own use. def _freeze_(self): Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 12:02:54 2010 @@ -613,14 +613,12 @@ def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) while True: + if vinfo is not None: + virtualizable = lltype.cast_opaque_ptr( + vinfo.VTYPEPTR, virtualizableref) + vinfo.reset_vable_token(virtualizable) try: - if vinfo is not None: - virtualizable = lltype.cast_opaque_ptr( - vinfo.VTYPEPTR, virtualizableref) - vinfo.reset_vable_token(virtualizable) - XXX # careful here, we must pass the correct jitdriver_sd - loop_token = fail_descr.handle_fail(self.metainterp_sd) - fail_descr = self.cpu.execute_token(loop_token) + loop_token = fail_descr.handle_fail(self.metainterp_sd, jd) except self.ContinueRunningNormally, e: args = () for ARGTYPE, attrname, count in portalfunc_ARGS: @@ -647,21 +645,21 @@ else: value = cast_base_ptr_to_instance(Exception, value) raise Exception, value + fail_descr = self.cpu.execute_token(loop_token) jd._assembler_call_helper = assembler_call_helper # for debugging - # XXX rewrite me, ugly sticking does not work any more - self.cpu.assembler_helper_ptr = self.helper_func( + jd._assembler_helper_ptr = self.helper_func( jd._PTR_ASSEMBLER_HELPER_FUNCTYPE, assembler_call_helper) - # XXX a bit ugly sticking + jd.assembler_helper_adr = llmemory.cast_ptr_to_adr( + jd._assembler_helper_ptr) if vinfo is not None: - XXX # rewrite me, ugly sticking does not work any more - self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - - self.num_green_args) - self.cpu.vable_token_descr = vinfo.vable_token_descr + jd.index_of_virtualizable = (vinfo.index_of_virtualizable - + self.num_green_args) + jd.vable_token_descr = vinfo.vable_token_descr else: - self.cpu.index_of_virtualizable = -1 - self.cpu.vable_token_descr = None + jd.index_of_virtualizable = -1 + jd.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr From arigo at codespeak.net Sat Jun 12 12:22:26 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:22:26 +0200 (CEST) Subject: [pypy-svn] r75320 - in pypy/trunk/pypy: jit/codewriter/test jit/metainterp jit/metainterp/test rpython rpython/lltypesystem translator/c translator/c/src Message-ID: <20100612102226.7E451282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:22:24 2010 New Revision: 75320 Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py pypy/trunk/pypy/jit/metainterp/blackhole.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py pypy/trunk/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/rpython/lltypesystem/opimpl.py pypy/trunk/pypy/rpython/lltypesystem/rclass.py pypy/trunk/pypy/rpython/normalizecalls.py pypy/trunk/pypy/translator/c/funcgen.py pypy/trunk/pypy/translator/c/src/int.h Log: Merge branch/int-between. It adds an 'int_between' operation produced by lltypesystem.rclass. This operation has a slightly more efficient form in the C backend. More importantly, in the JIT it becomes a single True/False test; previously, it was done with a double test "a <= b <= c", which can fail for two distinct reasons: b < a or b > c. If we ever see that case, it would create two equal traces from that point. Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Sat Jun 12 12:22:24 2010 @@ -715,3 +715,12 @@ uint_le %i2, $456L -> %i3 int_return %i3 """, transform=True) + + def test_int_between(self): + from pypy.rpython.lltypesystem.lloperation import llop + def f(n, m, p): + return llop.int_between(lltype.Bool, n, m, p) + self.encoding_test(f, [5, 6, 7], """ + int_between %i0, %i1, %i2 -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/trunk/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/blackhole.py (original) +++ pypy/trunk/pypy/jit/metainterp/blackhole.py Sat Jun 12 12:22:24 2010 @@ -475,6 +475,9 @@ @arguments("i", returns="i") def bhimpl_int_is_true(a): return bool(a) + @arguments("i", "i", "i", returns="i") + def bhimpl_int_between(a, b, c): + return a <= b < c @arguments("i", "i", returns="i") def bhimpl_uint_lt(a, b): Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 12:22:24 2010 @@ -315,6 +315,16 @@ if value: self.pc = target + @arguments("box", "box", "box") + def opimpl_int_between(self, b1, b2, b3): + b5 = self.execute(rop.INT_SUB, b3, b1) + if isinstance(b5, ConstInt) and b5.getint() == 1: + # the common case of int_between(a, b, a+1) turns into just INT_EQ + return self.execute(rop.INT_EQ, b2, b1) + else: + b4 = self.execute(rop.INT_SUB, b2, b1) + return self.execute(rop.UINT_LT, b4, b5) + @arguments("box", "descr", "orgpc") def opimpl_switch(self, valuebox, switchdict, orgpc): box = self.implement_guard_value(orgpc, valuebox) Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 12:22:24 2010 @@ -145,6 +145,9 @@ def check_operations_history(self, expected=None, **isns): # this can be used after interp_operations + if expected is not None: + expected = dict(expected) + expected['jump'] = 1 self.metainterp.staticdata.stats.check_history(expected, **isns) @@ -561,6 +564,53 @@ int_le=0, uint_le=1, int_sub=1) + def test_int_between(self): + # + def check(arg1, arg2, arg3, expect_result, **expect_operations): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop + loc = locals().copy() + exec py.code.Source(""" + def f(n, m, p): + arg1 = %(arg1)s + arg2 = %(arg2)s + arg3 = %(arg3)s + return llop.int_between(lltype.Bool, arg1, arg2, arg3) + """ % locals()).compile() in loc + res = self.interp_operations(loc['f'], [5, 6, 7]) + assert res == expect_result + self.check_operations_history(expect_operations) + # + check('n', 'm', 'p', True, int_sub=2, uint_lt=1) + check('n', 'p', 'm', False, int_sub=2, uint_lt=1) + # + check('n', 'm', 6, False, int_sub=2, uint_lt=1) + # + check('n', 4, 'p', False, int_sub=2, uint_lt=1) + check('n', 5, 'p', True, int_sub=2, uint_lt=1) + check('n', 8, 'p', False, int_sub=2, uint_lt=1) + # + check('n', 6, 7, True, int_sub=2, uint_lt=1) + # + check(-2, 'n', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'm', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'p', 'm', False, int_sub=2, uint_lt=1) + #check(0, 'n', 'p', True, uint_lt=1) xxx implement me + #check(0, 'm', 'p', True, uint_lt=1) + #check(0, 'p', 'm', False, uint_lt=1) + # + check(2, 'n', 6, True, int_sub=1, uint_lt=1) + check(2, 'm', 6, False, int_sub=1, uint_lt=1) + check(2, 'p', 6, False, int_sub=1, uint_lt=1) + check(5, 'n', 6, True, int_eq=1) # 6 == 5+1 + check(5, 'm', 6, False, int_eq=1) # 6 == 5+1 + # + check(2, 6, 'm', False, int_sub=1, uint_lt=1) + check(2, 6, 'p', True, int_sub=1, uint_lt=1) + # + check(2, 40, 6, False) + check(2, 40, 60, True) + def test_getfield(self): class A: pass Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Sat Jun 12 12:22:24 2010 @@ -227,6 +227,8 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), + 'int_between': LLOp(canfold=True), # a <= b < c + 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), # ^^^ more efficient version when 2nd arg is nonneg Modified: pypy/trunk/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/opimpl.py Sat Jun 12 12:22:24 2010 @@ -197,6 +197,12 @@ assert isinstance(y, int) return intmask(x - y) +def op_int_between(a, b, c): + assert lltype.typeOf(a) is lltype.Signed + assert lltype.typeOf(b) is lltype.Signed + assert lltype.typeOf(c) is lltype.Signed + return a <= b < c + def op_int_and(x, y): if not isinstance(x, int): from pypy.rpython.lltypesystem import llgroup Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Sat Jun 12 12:22:24 2010 @@ -22,6 +22,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel from pypy.lib.identity_dict import identity_dict +from pypy.rpython.lltypesystem.lloperation import llop # # There is one "vtable" per user class, with the following structure: @@ -645,10 +646,12 @@ return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): - return cls.subclassrange_min <= subcls.subclassrange_min <= cls.subclassrange_max + return llop.int_between(Bool, cls.subclassrange_min, + subcls.subclassrange_min, + cls.subclassrange_max) def ll_issubclass_const(subcls, minid, maxid): - return minid <= subcls.subclassrange_min <= maxid + return llop.int_between(Bool, minid, subcls.subclassrange_min, maxid) def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT Modified: pypy/trunk/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/trunk/pypy/rpython/normalizecalls.py (original) +++ pypy/trunk/pypy/rpython/normalizecalls.py Sat Jun 12 12:22:24 2010 @@ -292,6 +292,13 @@ else: return cmp(self.orderwitness, other.orderwitness) + # support for implementing int_between: (a<=b (b == a) + return '%s = (%s == %s); /* was INT_BETWEEN */' % ( + self.expr(op.result), + self.expr(op.args[1]), + self.expr(op.args[0])) + else: + return None # use the default assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/trunk/pypy/translator/c/src/int.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/int.h (original) +++ pypy/trunk/pypy/translator/c/src/int.h Sat Jun 12 12:22:24 2010 @@ -47,6 +47,14 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) +/* Implement INT_BETWEEN by optimizing for the common case where a and c + are constants (the 2nd subtraction below is then constant-folded), or + for the case of a == 0 (both subtractions are then constant-folded). + Note that the following line only works if a <= c in the first place, + which we assume is true. */ +#define OP_INT_BETWEEN(a,b,c,r) r = (((unsigned long)b - (unsigned long)a) \ + < ((unsigned long)c - (unsigned long)a)) + /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) From arigo at codespeak.net Sat Jun 12 12:22:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:22:44 +0200 (CEST) Subject: [pypy-svn] r75321 - pypy/branch/int-between Message-ID: <20100612102244.D111A282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:22:43 2010 New Revision: 75321 Removed: pypy/branch/int-between/ Log: Remove merged branch. From arigo at codespeak.net Sat Jun 12 12:39:54 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:39:54 +0200 (CEST) Subject: [pypy-svn] r75322 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612103954.440A9282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:39:52 2010 New Revision: 75322 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/virtualizable.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Log: Progress on virtualizables. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 12:39:52 2010 @@ -518,17 +518,11 @@ return not isstandard def _get_virtualizable_field_index(self, fielddescr): - vinfo = self.metainterp.jitdrivers_sd.virtualizable_info + # Get the index of a fielddescr. Must only be called for + # the "standard" virtualizable. + vinfo = self.metainterp.jitdriver_sd.virtualizable_info return vinfo.static_field_by_descrs[fielddescr] - def _get_virtualizable_array_field_descr(self, index): - vinfo = self.metainterp.jitdrivers_sd.virtualizable_info - return vinfo.array_field_descrs[index] - - def _get_virtualizable_array_descr(self, index): - vinfo = self.metainterp.jitdrivers_sd.virtualizable_info - return vinfo.array_descrs[index] - @arguments("orgpc", "box", "descr") def _opimpl_getfield_vable(self, pc, box, fielddescr): if self._nonstandard_virtualizable(pc, box): @@ -556,8 +550,10 @@ opimpl_setfield_vable_f = _opimpl_setfield_vable def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): + # Get the index of an array item: the index'th of the array + # described by arrayfielddescr. Must only be called for + # the "standard" virtualizable. indexbox = self.implement_guard_value(pc, indexbox) - xxxxxxx vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -607,7 +603,6 @@ arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, fdescr, box) return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) - xxxxxxx vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1795,7 +1790,9 @@ def initialize_virtualizable(self, original_boxes): vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: - virtualizable_box = original_boxes[vinfo.index_of_virtualizable] + index = (self.jitdriver_sd.num_green_args + + self.jitdriver_sd.index_of_virtualizable) + virtualizable_box = original_boxes[index] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) # The field 'virtualizable_boxes' is not even present # if 'virtualizable_info' is None. Check for that first. @@ -1922,13 +1919,8 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if 0: ## self._already_allocated_resume_virtuals is not None: - # resuming from a ResumeGuardForcedDescr: load the new values - # currently stored on the virtualizable fields - self.load_fields_from_virtualizable() - else: - # normal case: fill the virtualizable with the local boxes - self.synchronize_virtualizable() + # fill the virtualizable with the local boxes + self.synchronize_virtualizable() return inputargs_and_holes def check_synchronized_virtualizable(self): @@ -2060,8 +2052,8 @@ args = op.args[num_green_args + 1:] vinfo = targetjitdriver_sd.virtualizable_info if vinfo is not None: - vindex = vinfo.index_of_virtualizable - vbox = args[vindex - num_green_args] + index = targetjitdriver_sd.index_of_virtualizable + vbox = args[index] args = args + self.gen_load_from_other_virtualizable(vinfo, vbox) # ^^^ and not "+=", which makes 'args' a resizable list op.opnum = rop.CALL_ASSEMBLER Modified: pypy/branch/multijit-4/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/virtualizable.py Sat Jun 12 12:39:52 2010 @@ -14,9 +14,8 @@ TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 - def __init__(self, warmrunnerdesc): + def __init__(self, warmrunnerdesc, VTYPEPTR): self.warmrunnerdesc = warmrunnerdesc - jitdriver = warmrunnerdesc.jitdriver cpu = warmrunnerdesc.cpu if cpu.ts.name == 'ootype': import py @@ -24,11 +23,6 @@ self.cpu = cpu self.BoxArray = cpu.ts.BoxRef # - assert len(jitdriver.virtualizables) == 1 # for now - [vname] = jitdriver.virtualizables - index = len(jitdriver.greens) + jitdriver.reds.index(vname) - self.index_of_virtualizable = index - VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index] while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 12:39:52 2010 @@ -279,15 +279,25 @@ warmrunnerdesc=self) def make_virtualizable_infos(self): + vinfos = {} for jd in self.jitdrivers_sd: - if jd.jitdriver.virtualizables: - XXX + if not jd.jitdriver.virtualizables: + jd.virtualizable_info = None + jd.index_of_virtualizable = -1 + continue + # + jitdriver = jd.jitdriver + assert len(jitdriver.virtualizables) == 1 # for now + [vname] = jitdriver.virtualizables + # XXX skip the Voids here too + jd.index_of_virtualizable = jitdriver.reds.index(vname) + # + index = jd.num_green_args + jd.index_of_virtualizable + VTYPEPTR = jd._JIT_ENTER_FUNCTYPE.ARGS[index] + if VTYPEPTR not in vinfos: from pypy.jit.metainterp.virtualizable import VirtualizableInfo - vinfo = VirtualizableInfo(self) - YYY # share! - else: - vinfo = None - jd.virtualizable_info = vinfo + vinfos[VTYPEPTR] = VirtualizableInfo(self, VTYPEPTR) + jd.virtualizable_info = vinfos[VTYPEPTR] def make_exception_classes(self): @@ -654,12 +664,7 @@ jd.assembler_helper_adr = llmemory.cast_ptr_to_adr( jd._assembler_helper_ptr) if vinfo is not None: - jd.index_of_virtualizable = (vinfo.index_of_virtualizable - - self.num_green_args) jd.vable_token_descr = vinfo.vable_token_descr - else: - jd.index_of_virtualizable = -1 - jd.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Sat Jun 12 12:39:52 2010 @@ -207,6 +207,7 @@ metainterp_sd = self.warmrunnerdesc.metainterp_sd jitdriver_sd = self.jitdriver_sd vinfo = jitdriver_sd.virtualizable_info + index_of_virtualizable = jitdriver_sd.index_of_virtualizable num_green_args = jitdriver_sd.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() @@ -224,7 +225,7 @@ self.set_param_optimizer(OPTIMIZER_FULL) if vinfo is not None: - virtualizable = args[vinfo.index_of_virtualizable] + virtualizable = args[num_green_args + index_of_virtualizable] virtualizable = vinfo.cast_to_vtype(virtualizable) else: virtualizable = None @@ -433,6 +434,7 @@ if vinfo is not None: i0 = len(jitdriver_sd._red_args_types) num_green_args = jitdriver_sd.num_green_args + index_of_virtualizable = jitdriver_sd.index_of_virtualizable vable_static_fields = unrolling_iterable( zip(vinfo.static_extra_types, vinfo.static_fields)) vable_array_fields = unrolling_iterable( @@ -442,8 +444,7 @@ # def set_future_values_from_vinfo(*redargs): i = i0 - virtualizable = redargs[vinfo.index_of_virtualizable - - num_green_args] + virtualizable = redargs[index_of_virtualizable] virtualizable = vinfo.cast_to_vtype(virtualizable) for typecode, fieldname in vable_static_fields: x = getattr(virtualizable, fieldname) From arigo at codespeak.net Sat Jun 12 12:55:23 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 12:55:23 +0200 (CEST) Subject: [pypy-svn] r75323 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612105523.0AF5C282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 12:55:22 2010 New Revision: 75323 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py pypy/branch/multijit-4/pypy/jit/metainterp/history.py pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/resoperation.py pypy/branch/multijit-4/pypy/jit/metainterp/resume.py Log: test_virtualizable passes again. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/compile.py Sat Jun 12 12:55:22 2010 @@ -212,8 +212,6 @@ class ResumeDescr(AbstractFailDescr): def __init__(self, original_greenkey): self.original_greenkey = original_greenkey - def _clone_if_mutable(self): - raise NotImplementedError class ResumeGuardDescr(ResumeDescr): _counter = 0 # if < 0, there is one counter per value; @@ -327,8 +325,7 @@ send_bridge_to_backend(metainterp.staticdata, self, inputargs, new_loop.operations) - def _clone_if_mutable(self): - res = self.__class__(self.metainterp_sd, self.original_greenkey) + def copy_all_attrbutes_into(self, res): # XXX a bit ugly to have to list them all here res.rd_snapshot = self.rd_snapshot res.rd_frame_info_list = self.rd_frame_info_list @@ -336,10 +333,18 @@ res.rd_consts = self.rd_consts res.rd_virtuals = self.rd_virtuals res.rd_pendingfields = self.rd_pendingfields + + def _clone_if_mutable(self): + res = ResumeGuardDescr(self.metainterp_sd, self.original_greenkey) + self.copy_all_attrbutes_into(res) return res class ResumeGuardForcedDescr(ResumeGuardDescr): + def __init__(self, metainterp_sd, original_greenkey, jitdriver_sd): + ResumeGuardDescr.__init__(self, metainterp_sd, original_greenkey) + self.jitdriver_sd = jitdriver_sd + def handle_fail(self, metainterp_sd, jitdriver_sd): # Failures of a GUARD_NOT_FORCED are never compiled, but # always just blackholed. First fish for the data saved when @@ -350,6 +355,7 @@ all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] + assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, all_virtuals) assert 0, "unreachable" @@ -365,7 +371,8 @@ def handle_async_forcing(self, force_token): from pypy.jit.metainterp.resume import force_from_resumedata metainterp_sd = self.metainterp_sd - all_virtuals = force_from_resumedata(metainterp_sd, self) + vinfo = self.jitdriver_sd.virtualizable_info + all_virtuals = force_from_resumedata(metainterp_sd, self, vinfo) # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED @@ -399,6 +406,13 @@ assert 0, "not found: %r" % (key,) return data + def _clone_if_mutable(self): + res = ResumeGuardForcedDescr(self.metainterp_sd, + self.original_greenkey, + self.jitdriver_sd) + self.copy_all_attrbutes_into(res) + return res + class AbstractResumeGuardCounters(object): # Completely custom algorithm for now: keep 5 pairs (value, counter), Modified: pypy/branch/multijit-4/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/history.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/history.py Sat Jun 12 12:55:22 2010 @@ -125,9 +125,6 @@ def repr_of_descr(self): return '%r' % (self,) - def _clone_if_mutable(self): - return self - def get_arg_types(self): """ Implement in call descr. Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). @@ -171,6 +168,14 @@ """ raise NotImplementedError + def _clone_if_mutable(self): + return self + def clone_if_mutable(self): + clone = self._clone_if_mutable() + if not we_are_translated(): + assert clone.__class__ is self.__class__ + return clone + class AbstractFailDescr(AbstractDescr): index = -1 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 12:55:22 2010 @@ -939,7 +939,8 @@ original_greenkey = metainterp.resumekey.original_greenkey if opnum == rop.GUARD_NOT_FORCED: resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd, - original_greenkey) + original_greenkey, + metainterp.jitdriver_sd) else: resumedescr = compile.ResumeGuardDescr(metainterp_sd, original_greenkey) Modified: pypy/branch/multijit-4/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/resoperation.py Sat Jun 12 12:55:22 2010 @@ -34,7 +34,7 @@ def clone(self): descr = self.descr if descr is not None: - descr = descr._clone_if_mutable() + descr = descr.clone_if_mutable() op = ResOperation(self.opnum, self.args, self.result, descr) op.fail_args = self.fail_args if not we_are_translated(): Modified: pypy/branch/multijit-4/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/resume.py Sat Jun 12 12:55:22 2010 @@ -745,10 +745,9 @@ resumereader.done() return firstbh -def force_from_resumedata(metainterp_sd, storage): +def force_from_resumedata(metainterp_sd, storage, vinfo=None): resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) resumereader.handling_async_forcing() - vinfo = metainterp_sd.virtualizable_info vrefinfo = metainterp_sd.virtualref_info resumereader.consume_vref_and_vable(vrefinfo, vinfo) return resumereader.virtuals From arigo at codespeak.net Sat Jun 12 13:10:51 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 13:10:51 +0200 (CEST) Subject: [pypy-svn] r75324 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612111051.91E9F282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 13:10:50 2010 New Revision: 75324 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Log: Oups(1). Fix. Hard to test, it was triggered by mistake :-( Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 13:10:50 2010 @@ -2162,7 +2162,7 @@ argcode = argcodes[next_argcode] next_argcode = next_argcode + 1 if argcode == 'i': - value = ord(code[position]) + value = self.registers_i[ord(code[position])].getint() elif argcode == 'c': value = signedord(code[position]) else: From arigo at codespeak.net Sat Jun 12 13:18:03 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 13:18:03 +0200 (CEST) Subject: [pypy-svn] r75325 - in pypy/branch/multijit-4/pypy/jit/codewriter: . test Message-ID: <20100612111803.8265B282BEC@codespeak.net> Author: arigo Date: Sat Jun 12 13:18:02 2010 New Revision: 75325 Modified: pypy/branch/multijit-4/pypy/jit/codewriter/assembler.py pypy/branch/multijit-4/pypy/jit/codewriter/test/test_assembler.py Log: Test and fix. Modified: pypy/branch/multijit-4/pypy/jit/codewriter/assembler.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/assembler.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/assembler.py Sat Jun 12 13:18:02 2010 @@ -60,37 +60,38 @@ self.code.append(chr(reg.index)) def emit_const(self, const, kind, allow_short=False): - if const not in self.constants_dict: - value = const.value - TYPE = lltype.typeOf(value) - if kind == 'int': - if isinstance(TYPE, lltype.Ptr): - assert TYPE.TO._gckind == 'raw' - self.see_raw_object(value) - value = llmemory.cast_ptr_to_adr(value) - TYPE = llmemory.Address - if TYPE == llmemory.Address: - value = heaptracker.adr2int(value) - elif not isinstance(value, ComputedIntSymbolic): - value = lltype.cast_primitive(lltype.Signed, value) - if allow_short and -128 <= value <= 127: - # emit the constant as a small integer - self.code.append(chr(value & 0xFF)) - return True - constants = self.constants_i - elif kind == 'ref': - value = lltype.cast_opaque_ptr(llmemory.GCREF, value) - constants = self.constants_r - elif kind == 'float': - assert TYPE == lltype.Float - constants = self.constants_f - else: - raise NotImplementedError(const) + value = const.value + TYPE = lltype.typeOf(value) + if kind == 'int': + if isinstance(TYPE, lltype.Ptr): + assert TYPE.TO._gckind == 'raw' + self.see_raw_object(value) + value = llmemory.cast_ptr_to_adr(value) + TYPE = llmemory.Address + if TYPE == llmemory.Address: + value = heaptracker.adr2int(value) + elif not isinstance(value, ComputedIntSymbolic): + value = lltype.cast_primitive(lltype.Signed, value) + if allow_short and -128 <= value <= 127: + # emit the constant as a small integer + self.code.append(chr(value & 0xFF)) + return True + constants = self.constants_i + elif kind == 'ref': + value = lltype.cast_opaque_ptr(llmemory.GCREF, value) + constants = self.constants_r + elif kind == 'float': + assert TYPE == lltype.Float + constants = self.constants_f + else: + raise NotImplementedError(const) + key = (kind, Constant(value)) + if key not in self.constants_dict: constants.append(value) - self.constants_dict[const] = 256 - len(constants) + self.constants_dict[key] = 256 - len(constants) # emit the constant normally, as one byte that is an index in the # list of constants - self.code.append(chr(self.constants_dict[const])) + self.code.append(chr(self.constants_dict[key])) return False def write_insn(self, insn): Modified: pypy/branch/multijit-4/pypy/jit/codewriter/test/test_assembler.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/codewriter/test/test_assembler.py (original) +++ pypy/branch/multijit-4/pypy/jit/codewriter/test/test_assembler.py Sat Jun 12 13:18:02 2010 @@ -127,6 +127,25 @@ assert assembler.insns == {'foobar/IR': 0} assert jitcode.constants_i == [42] +def test_assemble_list_semibug(): + # the semibug is that after forcing 42 into the dict of constants, + # it would be reused for all future 42's, even ones that can be + # encoded directly. + ssarepr = SSARepr("test") + ssarepr.insns = [ + ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])), + ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])), + ('baz', Constant(42, lltype.Signed)), + ] + assembler = Assembler() + jitcode = assembler.assemble(ssarepr) + assert jitcode.code == ("\x00\x01\xFF" + "\x00\x01\xFF" + "\x01\x2A") + assert assembler.insns == {'foobar/I': 0, + 'baz/c': 1} + assert jitcode.constants_i == [42] + def test_assemble_descr(): class FooDescr(AbstractDescr): pass From arigo at codespeak.net Sat Jun 12 16:36:58 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 16:36:58 +0200 (CEST) Subject: [pypy-svn] r75326 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612143658.2E60A282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 16:36:56 2010 New Revision: 75326 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_pyjitpl.py Log: Fix test. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_pyjitpl.py Sat Jun 12 16:36:56 2010 @@ -17,9 +17,8 @@ portal.setup(None) class FakeStaticData: cpu = None - portal_code = portal - metainterp = pyjitpl.MetaInterp(FakeStaticData()) + metainterp = pyjitpl.MetaInterp(FakeStaticData(), None) metainterp.framestack = [] class FakeHistory: operations = [] @@ -59,7 +58,7 @@ assert isinstance(box, referencebox.clonebox().__class__) assert box.value == referencebox.value return True - metainterp = pyjitpl.MetaInterp(FakeStaticData()) + metainterp = pyjitpl.MetaInterp(FakeStaticData(), None) metainterp.history = History() b1 = BoxInt(1) b2 = BoxInt(2) From arigo at codespeak.net Sat Jun 12 16:49:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 16:49:34 +0200 (CEST) Subject: [pypy-svn] r75327 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612144934.7154D282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 16:49:32 2010 New Revision: 75327 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmstate.py Log: Fix tests. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmspot.py Sat Jun 12 16:49:32 2010 @@ -128,8 +128,9 @@ from pypy.jit.metainterp import optimize - assert warmrunnerdescr.state.optimize_loop is optimize.optimize_loop - assert warmrunnerdescr.state.optimize_bridge is optimize.optimize_bridge + state = warmrunnerdescr.jitdrivers_sd[0].warmstate + assert state.optimize_loop is optimize.optimize_loop + assert state.optimize_bridge is optimize.optimize_bridge def test_static_debug_level(self, capfd): py.test.skip("debug_level is being deprecated") @@ -294,7 +295,7 @@ def __init__(self, no): self.no = no - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdrivers_sd): if self.no == 0: raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: @@ -355,12 +356,13 @@ def test_call_helper(self): from pypy.rpython.llinterp import LLException - - assert self.desc.assembler_call_helper(0, 0) == 3 - assert self.desc.assembler_call_helper(1, 0) == 10 - assert self.desc.assembler_call_helper(2, 0) == 10 + + [jd] = self.desc.jitdrivers_sd + assert jd._assembler_call_helper(0, 0) == 3 + assert jd._assembler_call_helper(1, 0) == 10 + assert jd._assembler_call_helper(2, 0) == 10 try: - self.desc.assembler_call_helper(3, 0) + jd._assembler_call_helper(3, 0) except LLException, lle: assert lle[0] == self.exc_vtable else: Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_warmstate.py Sat Jun 12 16:49:32 2010 @@ -4,10 +4,9 @@ from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.warmstate import wrap, unwrap from pypy.jit.metainterp.warmstate import equal_whatever, hash_whatever -from pypy.jit.metainterp.warmstate import WarmEnterState +from pypy.jit.metainterp.warmstate import WarmEnterState, JitCell from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr from pypy.jit.metainterp.history import ConstInt, ConstFloat, ConstPtr -from pypy.rlib.jit import BaseJitCell def test_unwrap(): @@ -58,14 +57,12 @@ def test_make_jitcell_getter_default(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - class FakeJitCell(BaseJitCell): - pass - state = WarmEnterState(FakeWarmRunnerDesc()) - get_jitcell = state._make_jitcell_getter_default(FakeJitCell) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + state = WarmEnterState(None, FakeJitDriverSD()) + get_jitcell = state._make_jitcell_getter_default() cell1 = get_jitcell(42, 42.5) - assert isinstance(cell1, FakeJitCell) + assert isinstance(cell1, JitCell) cell2 = get_jitcell(42, 42.5) assert cell1 is cell2 cell3 = get_jitcell(41, 42.5) @@ -73,10 +70,10 @@ assert cell1 is not cell3 is not cell4 is not cell1 def test_make_jitcell_getter(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Float] - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Float] + _get_jitcell_at_ptr = None + state = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = state.make_jitcell_getter() cell1 = get_jitcell(1.75) cell2 = get_jitcell(1.75) @@ -87,8 +84,6 @@ from pypy.rpython.typesystem import LowLevelTypeSystem class FakeRTyper: type_system = LowLevelTypeSystem.instance - class FakeJitCell(BaseJitCell): - pass celldict = {} def getter(x, y): return celldict.get((x, y)) @@ -102,14 +97,14 @@ lltype.Float], lltype.Void)) class FakeWarmRunnerDesc: rtyper = FakeRTyper() - cpu = None - get_jitcell_at_ptr = llhelper(GETTER, getter) - set_jitcell_at_ptr = llhelper(SETTER, setter) + class FakeJitDriverSD: + _get_jitcell_at_ptr = llhelper(GETTER, getter) + _set_jitcell_at_ptr = llhelper(SETTER, setter) # - state = WarmEnterState(FakeWarmRunnerDesc()) - get_jitcell = state._make_jitcell_getter_custom(FakeJitCell) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) + get_jitcell = state._make_jitcell_getter_custom() cell1 = get_jitcell(5, 42.5) - assert isinstance(cell1, FakeJitCell) + assert isinstance(cell1, JitCell) assert cell1.x == 5 assert cell1.y == 42.5 cell2 = get_jitcell(5, 42.5) @@ -127,10 +122,11 @@ future_values[j] = "float", value class FakeWarmRunnerDesc: cpu = FakeCPU() - red_args_types = ["int", "float"] + class FakeJitDriverSD: + _red_args_types = ["int", "float"] virtualizable_info = None # - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) set_future_values = state.make_set_future_values() set_future_values(5, 42.5) assert future_values == { @@ -140,19 +136,19 @@ assert set_future_values is state.make_set_future_values() def test_make_unwrap_greenkey(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + state = WarmEnterState(None, FakeJitDriverSD()) unwrap_greenkey = state.make_unwrap_greenkey() greenargs = unwrap_greenkey([ConstInt(42), ConstFloat(42.5)]) assert greenargs == (42, 42.5) assert type(greenargs[0]) is int def test_attach_unoptimized_bridge_from_interp(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _get_jitcell_at_ptr = None + state = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = state.make_jitcell_getter() state.attach_unoptimized_bridge_from_interp([ConstInt(5), ConstFloat(2.25)], @@ -162,14 +158,14 @@ assert cell1.entry_loop_token == "entry loop token" def test_make_jitdriver_callbacks_1(): - class FakeWarmRunnerDesc: - can_inline_ptr = None - get_printable_location_ptr = None - confirm_enter_jit_ptr = None - green_args_spec = [lltype.Signed, lltype.Float] + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = None class FakeCell: dont_trace_here = False - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(None, FakeJitDriverSD()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter @@ -190,11 +186,12 @@ dont_trace_here = False class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = llhelper(CAN_INLINE, can_inline) - get_printable_location_ptr = None - confirm_enter_jit_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = llhelper(CAN_INLINE, can_inline) + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = None + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter @@ -211,12 +208,13 @@ lltype.Ptr(rstr.STR))) class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = None - get_printable_location_ptr = llhelper(GET_LOCATION, get_location) - confirm_enter_jit_ptr = None - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = llhelper(GET_LOCATION, get_location) + _confirm_enter_jit_ptr = None + _get_jitcell_at_ptr = None + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) state.make_jitdriver_callbacks() res = state.get_location_str([ConstInt(5), ConstFloat(42.5)]) assert res == "hi there" @@ -231,13 +229,14 @@ lltype.Signed], lltype.Bool)) class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = None - get_printable_location_ptr = None - confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit) - get_jitcell_at_ptr = None + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit) + _get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) state.make_jitdriver_callbacks() res = state.confirm_enter_jit(5, 42.5, 3) assert res is True From arigo at codespeak.net Sat Jun 12 17:06:19 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:06:19 +0200 (CEST) Subject: [pypy-svn] r75328 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100612150619.AA20F282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:06:18 2010 New Revision: 75328 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Log: Write another rough (passing) test. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Sat Jun 12 17:06:18 2010 @@ -3,12 +3,21 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin +def getloc1(): + return "in jitdriver1" + +def getloc2(g): + return "in jitdriver2, with g=%d" % g + + class MultipleJitDriversTests: def test_simple(self): myjitdriver1 = JitDriver(greens=[], reds=['n', 'm'], - can_inline = lambda *args: False) - myjitdriver2 = JitDriver(greens=['g'], reds=['r']) + can_inline = lambda *args: False, + get_printable_location = getloc1) + myjitdriver2 = JitDriver(greens=['g'], reds=['r'], + get_printable_location = getloc2) # def loop1(n, m): while n > 0: @@ -26,6 +35,41 @@ # res = self.meta_interp(loop2, [4, 40], repeat=7, inline=True) assert res == loop2(4, 40) + # the following numbers are not really expectations of the test + # itself, but just the numbers that we got after looking carefully + # at the generated machine code + self.check_loop_count(5) + self.check_tree_loop_count(4) # 2 x loop, 2 x enter bridge + self.check_enter_count(7) + + def test_simple_inline(self): + # this is not an example of reasonable code: loop1() is unrolled + # 'n/m' times, where n and m are given as red arguments. + myjitdriver1 = JitDriver(greens=[], reds=['n', 'm'], + can_inline = lambda *args: True, + get_printable_location = getloc1) + myjitdriver2 = JitDriver(greens=['g'], reds=['r'], + get_printable_location = getloc2) + # + def loop1(n, m): + while n > 0: + if n > 1000: + myjitdriver1.can_enter_jit(n=n, m=m) + myjitdriver1.jit_merge_point(n=n, m=m) + n -= m + return n + # + def loop2(g, r): + while r > 0: + myjitdriver2.can_enter_jit(g=g, r=r) + myjitdriver2.jit_merge_point(g=g, r=r) + r += loop1(r, g) - 1 + return r + # + res = self.meta_interp(loop2, [4, 40], repeat=7, inline=True) + assert res == loop2(4, 40) + # we expect no loop at all for 'loop1': it should always be inlined + self.check_tree_loop_count(2) # 1 x loop, 1 x enter bridge class TestLLtype(MultipleJitDriversTests, LLJitMixin): From arigo at codespeak.net Sat Jun 12 17:12:17 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:12:17 +0200 (CEST) Subject: [pypy-svn] r75329 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100612151217.C7025282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:12:16 2010 New Revision: 75329 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Log: Fix for translate.py (shown by backend/x86/test/test_zrpy_gc). Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sat Jun 12 17:12:16 2010 @@ -45,8 +45,9 @@ no_stats = True, ProfilerClass = ProfilerClass, **kwds) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_debug(debug_level) + for jd in warmrunnerdesc.jitdrivers_sd: + jd.warmstate.set_param_inlining(inline) + jd.warmstate.set_param_debug(debug_level) warmrunnerdesc.finish() translator.warmrunnerdesc = warmrunnerdesc # for later debugging From arigo at codespeak.net Sat Jun 12 17:13:34 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:13:34 +0200 (CEST) Subject: [pypy-svn] r75330 - in pypy/branch/multijit-4/pypy/jit/tl: . spli tinyframe tla Message-ID: <20100612151334.28FE7282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:13:32 2010 New Revision: 75330 Modified: pypy/branch/multijit-4/pypy/jit/tl/spli/targetspli.py pypy/branch/multijit-4/pypy/jit/tl/targettlc.py pypy/branch/multijit-4/pypy/jit/tl/targettlr.py pypy/branch/multijit-4/pypy/jit/tl/tinyframe/targettinyframe.py pypy/branch/multijit-4/pypy/jit/tl/tla/targettla.py Log: Fix import. Modified: pypy/branch/multijit-4/pypy/jit/tl/spli/targetspli.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/tl/spli/targetspli.py (original) +++ pypy/branch/multijit-4/pypy/jit/tl/spli/targetspli.py Sat Jun 12 17:13:32 2010 @@ -31,7 +31,7 @@ def jitpolicy(driver): """Returns the JIT policy to use when translating.""" - from pypy.jit.metainterp.policy import JitPolicy + from pypy.jit.codewriter.policy import JitPolicy return JitPolicy() if __name__ == '__main__': Modified: pypy/branch/multijit-4/pypy/jit/tl/targettlc.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/tl/targettlc.py (original) +++ pypy/branch/multijit-4/pypy/jit/tl/targettlc.py Sat Jun 12 17:13:32 2010 @@ -2,7 +2,7 @@ import py py.path.local(__file__) from pypy.jit.tl.tlc import interp, interp_nonjit, ConstantPool -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy from pypy.jit.backend.hlinfo import highleveljitinfo Modified: pypy/branch/multijit-4/pypy/jit/tl/targettlr.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/tl/targettlr.py (original) +++ pypy/branch/multijit-4/pypy/jit/tl/targettlr.py Sat Jun 12 17:13:32 2010 @@ -33,7 +33,7 @@ # ____________________________________________________________ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/branch/multijit-4/pypy/jit/tl/tinyframe/targettinyframe.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/tl/tinyframe/targettinyframe.py (original) +++ pypy/branch/multijit-4/pypy/jit/tl/tinyframe/targettinyframe.py Sat Jun 12 17:13:32 2010 @@ -1,6 +1,6 @@ from pypy.jit.tl.tinyframe.tinyframe import main -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/branch/multijit-4/pypy/jit/tl/tla/targettla.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/tl/tla/targettla.py (original) +++ pypy/branch/multijit-4/pypy/jit/tl/tla/targettla.py Sat Jun 12 17:13:32 2010 @@ -28,7 +28,7 @@ def target(driver, args): return entry_point, None -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() From arigo at codespeak.net Sat Jun 12 17:38:40 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:38:40 +0200 (CEST) Subject: [pypy-svn] r75331 - in pypy/trunk/pypy/module/__builtin__: . test Message-ID: <20100612153840.86BD0282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:38:34 2010 New Revision: 75331 Modified: pypy/trunk/pypy/module/__builtin__/functional.py pypy/trunk/pypy/module/__builtin__/test/test_functional.py Log: Test and fix. Modified: pypy/trunk/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/functional.py Sat Jun 12 17:38:34 2010 @@ -187,13 +187,15 @@ cont = False args_w = [space.w_None] * num_iterators for i in range(num_iterators): - try: - args_w[i] = space.next(iterators_w[i]) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - else: - cont = True + if iterators_w[i] is not None: + try: + args_w[i] = space.next(iterators_w[i]) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + iterators_w[i] = None + else: + cont = True if cont: w_args = space.newtuple(args_w) if none_func: Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_functional.py Sat Jun 12 17:38:34 2010 @@ -58,6 +58,23 @@ b = [] assert map(lambda x, y: x, a, b) == a + def test_map_iterables(self): + class A(object): + def __init__(self, n): + self.n = n + def __iter__(self): + return B(self.n) + class B(object): + def __init__(self, n): + self.n = n + def next(self): + self.n -= 1 + if self.n == 0: raise StopIteration + return self.n + result = map(None, A(3), A(8)) + assert result == [(2, 7), (1, 6), (None, 5), (None, 4), + (None, 3), (None, 2), (None, 1)] + class AppTestZip: def test_one_list(self): assert zip([1,2,3]) == [(1,), (2,), (3,)] From arigo at codespeak.net Sat Jun 12 17:40:10 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:40:10 +0200 (CEST) Subject: [pypy-svn] r75332 - pypy/trunk/pypy/module/__builtin__/test Message-ID: <20100612154010.6F2C5282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:40:08 2010 New Revision: 75332 Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py Log: Comment. Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_functional.py Sat Jun 12 17:40:08 2010 @@ -72,6 +72,8 @@ if self.n == 0: raise StopIteration return self.n result = map(None, A(3), A(8)) + # this also checks that B.next() is not called any more after it + # raised StopIteration once assert result == [(2, 7), (1, 6), (None, 5), (None, 4), (None, 3), (None, 2), (None, 1)] From arigo at codespeak.net Sat Jun 12 17:42:02 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 17:42:02 +0200 (CEST) Subject: [pypy-svn] r75333 - pypy/trunk/pypy/module/__builtin__/test Message-ID: <20100612154202.65108282B9C@codespeak.net> Author: arigo Date: Sat Jun 12 17:42:01 2010 New Revision: 75333 Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py Log: Bah. One test was never run because it had the same name as a later test, and it contained (of course) a typo. Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_functional.py Sat Jun 12 17:42:01 2010 @@ -48,12 +48,12 @@ b = [ 2, 3, 4, 5, 6] assert map(None, a, b) == [('1', 2), (2, 3), (3, 4), ('b', 5), (None, 6)] - def test_map_multiply(self): + def test_map_add(self): a = [1, 2, 3, 4] b = [0, 1, 1, 1] - assert map(lambda x, y: x+y, a, b) == [1, 2, 4, 5] + assert map(lambda x, y: x+y, a, b) == [1, 3, 4, 5] - def test_map_multiply(self): + def test_map_first_item(self): a = [1, 2, 3, 4, 5] b = [] assert map(lambda x, y: x, a, b) == a From arigo at codespeak.net Sat Jun 12 18:58:46 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 18:58:46 +0200 (CEST) Subject: [pypy-svn] r75334 - in pypy/trunk/pypy: interpreter/test lib/app_test lib/app_test/ctypes_tests module/__builtin__/test module/_codecs/test module/_file/test module/imp/test module/itertools/test objspace/std/test rlib/parsing/test rpython/numpy/test rpython/ootypesystem/test rpython/test translator/c/test Message-ID: <20100612165846.E74D6282BD8@codespeak.net> Author: arigo Date: Sat Jun 12 18:58:43 2010 New Revision: 75334 Modified: pypy/trunk/pypy/interpreter/test/test_function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_unicode.py pypy/trunk/pypy/lib/app_test/test_functools.py pypy/trunk/pypy/module/__builtin__/test/test_classobj.py pypy/trunk/pypy/module/_codecs/test/test_codecs.py pypy/trunk/pypy/module/_file/test/test_file_extra.py pypy/trunk/pypy/module/imp/test/test_app.py pypy/trunk/pypy/module/itertools/test/test_itertools.py pypy/trunk/pypy/objspace/std/test/test_tupleobject.py pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py pypy/trunk/pypy/rlib/parsing/test/test_regexparse.py pypy/trunk/pypy/rpython/numpy/test/test_array.py pypy/trunk/pypy/rpython/ootypesystem/test/test_oolist.py pypy/trunk/pypy/rpython/test/test_rlist.py pypy/trunk/pypy/translator/c/test/test_extfunc.py pypy/trunk/pypy/translator/c/test/test_typed.py Log: Fix duplicate function names, i.e. places where we had two tests called 'test_'. Found using PyFlakes (thanks exarkun for the pointer). Modified: pypy/trunk/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_function.py (original) +++ pypy/trunk/pypy/interpreter/test/test_function.py Sat Jun 12 18:58:43 2010 @@ -158,13 +158,6 @@ assert res[0] == 42 assert res[1] == {'something': 23} - def test_kwargs_sets_positional_mixed(self): - def func(arg1, **kw): - return arg1, kw - res = func(arg1=42, something=23) - assert res[0] == 42 - assert res[1] == {'something': 23} - def test_kwargs_sets_positional_twice(self): def func(arg1, **kw): return arg1, kw Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py Sat Jun 12 18:58:43 2010 @@ -210,7 +210,7 @@ result = f(byref(c_int(99))) assert not result.contents == 99 - def test_errors(self): + def test_errors_1(self): f = dll._testfunc_p_p f.restype = c_int @@ -305,7 +305,7 @@ assert 13577625587 == f(1000000000000, cb) - def test_errors(self): + def test_errors_2(self): raises(AttributeError, getattr, dll, "_xxx_yyy") raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_unicode.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_unicode.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_unicode.py Sat Jun 12 18:58:43 2010 @@ -90,7 +90,7 @@ assert func(u"abc") == "abc" assert func(u"????") == "" - def test_ascii_replace(self): + def test_ascii_replace_2(self): ctypes.set_conversion_mode("ascii", "replace") assert func("abc") == "abc" assert func(u"abc") == "abc" Modified: pypy/trunk/pypy/lib/app_test/test_functools.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/test_functools.py (original) +++ pypy/trunk/pypy/lib/app_test/test_functools.py Sat Jun 12 18:58:43 2010 @@ -31,7 +31,7 @@ p = self.thetype(map, lambda x: x*10) assert p([1,2,3,4]) == [10, 20, 30, 40] - def test_attributes(self): + def test_attributes_1(self): p = self.thetype(capture, 1, 2, a=10, b=20) # attributes should be readable assert p.func == capture @@ -118,7 +118,7 @@ py.test.raises(ZeroDivisionError, self.thetype(f), 1, 0) py.test.raises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): + def test_attributes_2(self): p = self.thetype(hex) try: del p.__dict__ Modified: pypy/trunk/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_classobj.py Sat Jun 12 18:58:43 2010 @@ -477,7 +477,7 @@ assert a is a1 assert a.l == [1, 2] - def test_cmp(self): + def test_cmp_and_coerce(self): class A: def __coerce__(self, other): return (1, 2) Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Sat Jun 12 18:58:43 2010 @@ -373,7 +373,7 @@ decoded = _codecs.unicode_escape_decode(s)[0] assert decoded == '' - def test_charmap_decode(self): + def test_charmap_decode_1(self): import codecs res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab") assert res == (u"ab\ufffd", 3) @@ -525,7 +525,7 @@ def test_charmap_encode(self): assert 'xxx'.encode('charmap') == 'xxx' - def test_charmap_decode(self): + def test_charmap_decode_2(self): assert 'foo'.decode('charmap') == 'foo' def test_utf7_start_end_in_exception(self): Modified: pypy/trunk/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/trunk/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/trunk/pypy/module/_file/test/test_file_extra.py Sat Jun 12 18:58:43 2010 @@ -71,12 +71,6 @@ inputlines = list(self.file) assert inputlines == self.expected_lines - def test_repr(self): - r = repr(self.file) - assert r.find('open file') >= 0 - assert r.find(self.file.name) >= 0 - assert r.find(self.file.mode) >= 0 - def test_isatty(self): assert not self.file.isatty() Modified: pypy/trunk/pypy/module/imp/test/test_app.py ============================================================================== --- pypy/trunk/pypy/module/imp/test/test_app.py (original) +++ pypy/trunk/pypy/module/imp/test/test_app.py Sat Jun 12 18:58:43 2010 @@ -71,7 +71,8 @@ import test_imp_extra_AUTO1 assert mod is test_imp_extra_AUTO1 - def test_load_module_pyc(self): + def test_load_module_pyc_1(self): + import os fn = self._pyc_file() try: descr = ('.pyc', 'rb', self.imp.PY_COMPILED) @@ -91,7 +92,7 @@ import test_imp_extra_AUTO3 assert mod is test_imp_extra_AUTO3 - def test_load_module_pyc(self): + def test_load_module_pyc_2(self): import os fn = self._pyc_file() try: Modified: pypy/trunk/pypy/module/itertools/test/test_itertools.py ============================================================================== --- pypy/trunk/pypy/module/itertools/test/test_itertools.py (original) +++ pypy/trunk/pypy/module/itertools/test/test_itertools.py Sat Jun 12 18:58:43 2010 @@ -130,7 +130,7 @@ raises(StopIteration, it.next) - def test_takewhile_wrongargs(self): + def test_dropwhile_wrongargs(self): import itertools it = itertools.dropwhile(None, [1]) Modified: pypy/trunk/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_tupleobject.py Sat Jun 12 18:58:43 2010 @@ -289,7 +289,7 @@ assert (t * 1) is not t assert (t * 1) == t - def test_getslice(self): + def test_getslice_2(self): assert (5,2,3)[1:2] == (2,) def test_eq(self): Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Sat Jun 12 18:58:43 2010 @@ -321,7 +321,7 @@ assert U(u'test') == u'test' assert U(u'test').__class__ is U - def test_call_unicode(self): + def test_call_unicode_2(self): class X(object): def __unicode__(self): return u'x' Modified: pypy/trunk/pypy/rlib/parsing/test/test_regexparse.py ============================================================================== --- pypy/trunk/pypy/rlib/parsing/test/test_regexparse.py (original) +++ pypy/trunk/pypy/rlib/parsing/test/test_regexparse.py Sat Jun 12 18:58:43 2010 @@ -24,7 +24,7 @@ assert r.recognize("kjsadfq3jlflASDF@#$") assert r.recognize("vka afj ASF# A") -def test_quoted(): +def test_quoted_1(): r = make_runner("\\(*") assert r.recognize("(") assert not r.recognize("\\(") @@ -77,7 +77,7 @@ assert not r.recognize("a") assert not r.recognize("c") -def test_quoted(): +def test_quoted_2(): r = make_runner('\\[|\\]|\\|') assert r.recognize("[") assert r.recognize("|") Modified: pypy/trunk/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/trunk/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/trunk/pypy/rpython/numpy/test/test_array.py Sat Jun 12 18:58:43 2010 @@ -3,7 +3,8 @@ """ import py -numpy = py.test.importorskip("numpy") +py.test.skip("numpy - broken") + import pypy.rpython.numpy.implementation from pypy.annotation import model as annmodel from pypy.annotation.model import SomeObject, SomeInteger, SomeChar, SomeTuple @@ -270,7 +271,7 @@ assert s.ndim == 1 assert s.typecode == 'l' - def test_annotate_indexing(self): + def test_annotate_indexing_2(self): def f(): a = numpy.empty((4,3), dtype='i') c = a[:,0] Modified: pypy/trunk/pypy/rpython/ootypesystem/test/test_oolist.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/test/test_oolist.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/test/test_oolist.py Sat Jun 12 18:58:43 2010 @@ -122,14 +122,6 @@ res = interpret(f, [3], type_system="ootype") assert res == 3 - def test_initialize(self): - def f(x): - l = [1, 2] - l.append(x) - return l[2] - res = interpret(f, [3], type_system="ootype") - assert res == 3 - def test_listtype_explosion(self): def f(x): l1 = [x] Modified: pypy/trunk/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rlist.py (original) +++ pypy/trunk/pypy/rpython/test/test_rlist.py Sat Jun 12 18:58:43 2010 @@ -10,7 +10,6 @@ from pypy.rpython.lltypesystem import rlist as ll_rlist from pypy.rpython.ootypesystem import rlist as oo_rlist from pypy.rpython.rint import signed_repr -from pypy.translator.translator import TranslationContext from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin @@ -1070,7 +1069,7 @@ assert res == 0 - def test_getitem_exc(self): + def test_getitem_exc_1(self): def f(x): l = [1] return l[x] @@ -1115,7 +1114,7 @@ res = self.interpret(f, [0]) assert res == 1 - def test_getitem_exc(self): + def test_getitem_exc_2(self): def f(x): l = [1] return l[x] Modified: pypy/trunk/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/trunk/pypy/translator/c/test/test_extfunc.py Sat Jun 12 18:58:43 2010 @@ -221,13 +221,6 @@ res = f1() assert res == os.getcwd() -def test_strerror(): - def does_stuff(): - return os.strerror(2) - f1 = compile(does_stuff, []) - res = f1() - assert res == os.strerror(2) - def test_system(): def does_stuff(cmd): return os.system(cmd) Modified: pypy/trunk/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_typed.py (original) +++ pypy/trunk/pypy/translator/c/test/test_typed.py Sat Jun 12 18:58:43 2010 @@ -79,11 +79,6 @@ nested_whiles = self.getcompiled(snippet.nested_whiles, [int, int]) assert nested_whiles(5,3) == '!!!!!' - def test_call_five(self): - call_five = self.getcompiled(snippet.call_five, [int]) - result = call_five() - assert result == [5] - def test_call_unpack_56(self): call_unpack_56 = self.getcompiled(snippet.call_unpack_56, []) result = call_unpack_56() @@ -116,13 +111,6 @@ assert fn(4) == 789 assert fn(5) == 101112 - def test_get_set_del_slice(self): - fn = self.getcompiled(snippet.get_set_del_slice, [list]) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - def test_type_conversion(self): # obfuscated test case specially for typer.insert_link_conversions() def type_conversion(n): From arigo at codespeak.net Sat Jun 12 19:01:13 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jun 2010 19:01:13 +0200 (CEST) Subject: [pypy-svn] r75335 - in pypy/trunk/pypy: jit/backend/llgraph jit/backend/x86/test jit/codewriter jit/metainterp/test objspace/std objspace/std/test rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gc rpython/ootypesystem rpython/test rpython/tool tool Message-ID: <20100612170113.C1AFC282BD8@codespeak.net> Author: arigo Date: Sat Jun 12 19:01:10 2010 New Revision: 75335 Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py pypy/trunk/pypy/jit/codewriter/support.py pypy/trunk/pypy/jit/metainterp/test/test_loop.py pypy/trunk/pypy/jit/metainterp/test/test_recursive.py pypy/trunk/pypy/objspace/std/dictmultiobject.py pypy/trunk/pypy/objspace/std/dicttype.py pypy/trunk/pypy/objspace/std/frame.py pypy/trunk/pypy/objspace/std/settype.py pypy/trunk/pypy/objspace/std/stringobject.py pypy/trunk/pypy/objspace/std/test/test_strutil.py pypy/trunk/pypy/objspace/std/test/test_typeobject.py pypy/trunk/pypy/objspace/std/transparent.py pypy/trunk/pypy/rlib/rgc.py pypy/trunk/pypy/rlib/test/test_rbigint.py pypy/trunk/pypy/rlib/test/test_rmmap.py pypy/trunk/pypy/rpython/lltypesystem/llarena.py pypy/trunk/pypy/rpython/lltypesystem/lltype.py pypy/trunk/pypy/rpython/lltypesystem/rclass.py pypy/trunk/pypy/rpython/lltypesystem/rffi.py pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py pypy/trunk/pypy/rpython/memory/gc/generation.py pypy/trunk/pypy/rpython/memory/gc/marksweep.py pypy/trunk/pypy/rpython/ootypesystem/ootype.py pypy/trunk/pypy/rpython/ootypesystem/rootype.py pypy/trunk/pypy/rpython/rbuiltin.py pypy/trunk/pypy/rpython/test/test_llinterp.py pypy/trunk/pypy/rpython/test/test_rfloat.py pypy/trunk/pypy/rpython/test/test_rint.py pypy/trunk/pypy/rpython/test/test_rvirtualizable2.py pypy/trunk/pypy/rpython/tool/rffi_platform.py pypy/trunk/pypy/tool/sourcetools.py Log: A whole bunch of extra hits of PyFlakes (I gave up after a while). Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py Sat Jun 12 19:01:10 2010 @@ -4,7 +4,6 @@ when executing on top of the llinterpreter. """ -import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel from pypy.jit.metainterp.history import (ConstInt, ConstPtr, Modified: pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.codewriter import heaptracker @@ -22,7 +22,6 @@ from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc from pypy.jit.backend.x86.regalloc import X86RegisterManager, X86FrameManager,\ X86XMMRegisterManager -from pypy.rpython.annlowlevel import llhelper class MockGcRootMap(object): def get_basic_shape(self): Modified: pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, LoopToken, BasicFailDescr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache Modified: pypy/trunk/pypy/jit/codewriter/support.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/support.py (original) +++ pypy/trunk/pypy/jit/codewriter/support.py Sat Jun 12 19:01:10 2010 @@ -16,7 +16,6 @@ from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import MixLevelHelperAnnotator -from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.metainterp.typesystem import deref from pypy.rlib import rgc Modified: pypy/trunk/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_loop.py Sat Jun 12 19:01:10 2010 @@ -2,7 +2,6 @@ from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.objectmodel import compute_hash from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats -from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop Modified: pypy/trunk/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_recursive.py Sat Jun 12 19:01:10 2010 @@ -180,7 +180,6 @@ py.test.fail("DID NOT RAISE") def test_guard_failure_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -217,7 +216,6 @@ assert res == 0 def test_guard_failure_and_then_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -261,7 +259,6 @@ assert res == main(1000) def test_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -307,7 +304,6 @@ # this passes, if the blackholing shortcut for calls is turned off # it fails, it is very delicate in terms of parameters, # bridge/loop creation order - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/trunk/pypy/objspace/std/dictmultiobject.py Sat Jun 12 19:01:10 2010 @@ -467,7 +467,7 @@ # XXX fix this thing -import time, py +import time class DictInfo(object): _dict_infos = [] Modified: pypy/trunk/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/pypy/objspace/std/dicttype.py Sat Jun 12 19:01:10 2010 @@ -4,7 +4,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.stdtypedef import StdTypeDef, SMM, no_hash_descr from pypy.objspace.std.register_all import register_all -from pypy.interpreter.error import OperationError dict_copy = SMM('copy', 1, doc='D.copy() -> a shallow copy of D') Modified: pypy/trunk/pypy/objspace/std/frame.py ============================================================================== --- pypy/trunk/pypy/objspace/std/frame.py (original) +++ pypy/trunk/pypy/objspace/std/frame.py Sat Jun 12 19:01:10 2010 @@ -130,7 +130,7 @@ w_result = getattr(f, attr)(w_1, w_2) break else: - raise pyopcde.BytecodeCorruption, "bad COMPARE_OP oparg" + raise pyopcode.BytecodeCorruption, "bad COMPARE_OP oparg" f.pushvalue(w_result) @@ -154,6 +154,7 @@ if space.config.objspace.std.optimized_comparison_op: StdObjSpaceFrame.COMPARE_OP = fast_COMPARE_OP if space.config.objspace.std.logspaceoptypes: + assert 0, "logspaceoptypes: a few fixes a missing here" StdObjSpace._space_op_types = [] for name, new in get_logging(): setattr(StdObjSpaceFrame, name, new) Modified: pypy/trunk/pypy/objspace/std/settype.py ============================================================================== --- pypy/trunk/pypy/objspace/std/settype.py (original) +++ pypy/trunk/pypy/objspace/std/settype.py Sat Jun 12 19:01:10 2010 @@ -2,7 +2,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr, SMM -from pypy.interpreter import gateway set_add = SMM('add', 2, doc='Add an element to a set.\n\nThis' Modified: pypy/trunk/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/stringobject.py (original) +++ pypy/trunk/pypy/objspace/std/stringobject.py Sat Jun 12 19:01:10 2010 @@ -964,7 +964,6 @@ return mod_format(space, w_format, w_values, do_unicode=False) def buffer__String(space, w_string): - from pypy.interpreter.buffer import StringBuffer return space.wrap(StringBuffer(w_string._value)) # register all methods Modified: pypy/trunk/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_strutil.py Sat Jun 12 19:01:10 2010 @@ -2,8 +2,6 @@ from pypy.objspace.std.strutil import * from pypy.interpreter.error import OperationError -import py - class TestStrUtil: Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_typeobject.py Sat Jun 12 19:01:10 2010 @@ -1001,12 +1001,12 @@ y.x = 3 assert y.x == 3 - def ga(self, name): - return 'GA' + def ga2(self, name): + return 'GA2' - X.__getattribute__ = ga + X.__getattribute__ = ga2 - assert y.x == 'GA' + assert y.x == 'GA2' class TestNewShortcut: Modified: pypy/trunk/pypy/objspace/std/transparent.py ============================================================================== --- pypy/trunk/pypy/objspace/std/transparent.py (original) +++ pypy/trunk/pypy/objspace/std/transparent.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,6 @@ """ from pypy.interpreter import gateway -from pypy.interpreter.function import Function from pypy.interpreter.error import OperationError, operationerrfmt from pypy.objspace.std.proxyobject import * from pypy.objspace.std.typeobject import W_TypeObject Modified: pypy/trunk/pypy/rlib/rgc.py ============================================================================== --- pypy/trunk/pypy/rlib/rgc.py (original) +++ pypy/trunk/pypy/rlib/rgc.py Sat Jun 12 19:01:10 2010 @@ -201,7 +201,6 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP - from pypy.rpython.lltypesystem import lltype hop.exception_is_here() return hop.genop('gc_heap_stats', [], resulttype=hop.r_result) Modified: pypy/trunk/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rbigint.py (original) +++ pypy/trunk/pypy/rlib/test/test_rbigint.py Sat Jun 12 19:01:10 2010 @@ -55,8 +55,6 @@ assert r1.tolong() == r2 def test_touint(self): - import sys - from pypy.rlib.rarithmetic import r_uint result = r_uint(sys.maxint + 42) rl = rbigint.fromint(sys.maxint).add(rbigint.fromint(42)) assert rl.touint() == result Modified: pypy/trunk/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rmmap.py (original) +++ pypy/trunk/pypy/rlib/test/test_rmmap.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rlib import rmmap as mmap from pypy.rlib.rmmap import RTypeError, RValueError, alloc, free -import sys class TestMMap: def setup_class(cls): Modified: pypy/trunk/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/llarena.py Sat Jun 12 19:01:10 2010 @@ -1,5 +1,5 @@ import array, weakref -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import llmemory # An "arena" is a large area of memory which can hold a number of # objects, not necessarily all of the same type or size. It's used by Modified: pypy/trunk/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lltype.py Sat Jun 12 19:01:10 2010 @@ -12,7 +12,6 @@ from pypy.lib.identity_dict import identity_dict from types import NoneType from sys import maxint -import struct import weakref TLS = tlsobject() Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Sat Jun 12 19:01:10 2010 @@ -14,7 +14,7 @@ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ Array, Char, Void, \ - FuncType, Bool, Signed, functionptr, FuncType, PyObject + FuncType, Bool, Signed, functionptr, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr -from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof, raw_memcopy +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic @@ -11,7 +11,6 @@ from pypy.rlib import rarithmetic, rgc from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.annlowlevel import llhelper @@ -785,7 +784,6 @@ # the hint is present in structures probed by rffi_platform. size = tp._hints.get('size') if size is None: - from pypy.rpython.lltypesystem import llmemory size = llmemory.sizeof(tp) # a symbolic result in this case return size if isinstance(tp, lltype.Ptr): @@ -814,7 +812,6 @@ if name == fieldname: return fieldoffsets[index] # a symbolic result as a fallback - from pypy.rpython.lltypesystem import llmemory return llmemory.offsetof(STRUCT, fieldname) offsetof._annspecialcase_ = 'specialize:memo' Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sat Jun 12 19:01:10 2010 @@ -15,7 +15,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper -from pypy.tool.udir import udir class TestLL2Ctypes(object): Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py Sat Jun 12 19:01:10 2010 @@ -722,7 +722,6 @@ def test_name_clash(): import re - from pypy.rpython.lltypesystem import lltype fn = lltype.__file__ if fn.lower().endswith('pyc') or fn.lower().endswith('pyo'): fn = fn[:-1] Modified: pypy/trunk/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gc/generation.py (original) +++ pypy/trunk/pypy/rpython/memory/gc/generation.py Sat Jun 12 19:01:10 2010 @@ -720,7 +720,7 @@ return pos elif sys.platform == 'darwin': - from pypy.rpython.lltypesystem import lltype, rffi + from pypy.rpython.lltypesystem import rffi sysctlbyname = rffi.llexternal('sysctlbyname', [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP, Modified: pypy/trunk/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/trunk/pypy/rpython/memory/gc/marksweep.py Sat Jun 12 19:01:10 2010 @@ -242,7 +242,6 @@ # 3. walk the list of objects-with-del and for the ones not marked: # call __del__, move the object to the list of object-without-del import time - from pypy.rpython.lltypesystem.lloperation import llop debug_start("gc-collect") start_time = time.time() self.collect_in_progress = True Modified: pypy/trunk/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/ootype.py Sat Jun 12 19:01:10 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \ Primitive, isCompatibleType, enforce, saferecursive, SignedLongLong, UnsignedLongLong -from pypy.rpython.lltypesystem.lltype import frozendict, isCompatibleType +from pypy.rpython.lltypesystem.lltype import frozendict from pypy.rpython.lltypesystem.lltype import identityhash from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel Modified: pypy/trunk/pypy/rpython/ootypesystem/rootype.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/rootype.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/rootype.py Sat Jun 12 19:01:10 2010 @@ -157,13 +157,6 @@ def __init__(self, METHODTYPE): self.lowleveltype = METHODTYPE - def rtype_simple_call(self, hop): - vlist = hop.inputargs(*hop.args_r) - cgraphs = hop.inputconst(ootype.Void, None) - vlist.append(cgraphs) - hop.exception_is_here() - return hop.genop("indirect_call", vlist, resulttype = hop.r_result.lowleveltype) - def rtype_call_args(self, hop): from pypy.rpython.rbuiltin import call_args_expand hop, _ = call_args_expand(hop, takes_kwds=False) Modified: pypy/trunk/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/rbuiltin.py Sat Jun 12 19:01:10 2010 @@ -529,8 +529,6 @@ # _________________________________________________________________ # memory addresses -from pypy.rpython.lltypesystem import llmemory - def rtype_raw_malloc(hop): v_size, = hop.inputargs(lltype.Signed) return hop.genop('raw_malloc', [v_size], resulttype=llmemory.Address) Modified: pypy/trunk/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_llinterp.py (original) +++ pypy/trunk/pypy/rpython/test/test_llinterp.py Sat Jun 12 19:01:10 2010 @@ -307,7 +307,6 @@ assert res._obj.value == 3L def test_ovf(): - import sys def f(x): try: return ovfcheck(sys.maxint + x) @@ -328,7 +327,6 @@ assert res == 15 def test_floordiv_ovf_zer(): - import sys def f(x): try: return ovfcheck((-sys.maxint - 1) // x) @@ -344,7 +342,6 @@ assert res == (-sys.maxint - 1) // 30 def test_mod_ovf_zer(): - import sys def f(x): try: return ovfcheck((-sys.maxint - 1) % x) Modified: pypy/trunk/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rfloat.py (original) +++ pypy/trunk/pypy/rpython/test/test_rfloat.py Sat Jun 12 19:01:10 2010 @@ -77,7 +77,6 @@ assert res == fn(2.34) def test_longlong_conversion(self): - import sys def fn(f): return r_longlong(f) Modified: pypy/trunk/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rint.py (original) +++ pypy/trunk/pypy/rpython/test/test_rint.py Sat Jun 12 19:01:10 2010 @@ -169,7 +169,6 @@ assert res == 0 def test_truediv(self): - import operator def f(n, m): return operator.truediv(n, m) res = self.interpret(f, [20, 4]) Modified: pypy/trunk/pypy/rpython/test/test_rvirtualizable2.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rvirtualizable2.py (original) +++ pypy/trunk/pypy/rpython/test/test_rvirtualizable2.py Sat Jun 12 19:01:10 2010 @@ -311,7 +311,7 @@ assert res == 2323 def test_access_directly_stop_at_dont_look_inside(self): - from pypy.rlib.jit import hint, dont_look_inside + from pypy.rlib.jit import dont_look_inside class A: _virtualizable2_ = ['x'] Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/trunk/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/trunk/pypy/rpython/tool/rffi_platform.py Sat Jun 12 19:01:10 2010 @@ -752,7 +752,7 @@ 'struct sockaddr_in' sin_port INT """ - import sys, getopt + import getopt opts, args = getopt.gnu_getopt(sys.argv[1:], 'h:') if not args: print >> sys.stderr, doc Modified: pypy/trunk/pypy/tool/sourcetools.py ============================================================================== --- pypy/trunk/pypy/tool/sourcetools.py (original) +++ pypy/trunk/pypy/tool/sourcetools.py Sat Jun 12 19:01:10 2010 @@ -129,7 +129,6 @@ for name in names: if name not in kwargs: kwargs[name] = getattr(fromcode, name) - import new return new.code( kwargs['co_argcount'], kwargs['co_nlocals'], From fijal at codespeak.net Sat Jun 12 19:03:29 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 19:03:29 +0200 (CEST) Subject: [pypy-svn] r75336 - pypy/trunk/pypy/module/cpyext Message-ID: <20100612170329.53AF8282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 19:03:27 2010 New Revision: 75336 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Darwin does not like -Werror=implicit-function-declaration Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Sat Jun 12 19:03:27 2010 @@ -801,7 +801,7 @@ if sys.platform == "win32": # '%s' undefined; assuming extern returning int compile_extra.append("/we4013") - else: + elif sys.platform == 'linux2': compile_extra.append("-Werror=implicit-function-declaration") export_symbols_eci.append('pypyAPI') else: From fijal at codespeak.net Sat Jun 12 19:48:36 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 19:48:36 +0200 (CEST) Subject: [pypy-svn] r75337 - pypy/trunk/pypy/module/cpyext Message-ID: <20100612174836.317DD282B9C@codespeak.net> Author: fijal Date: Sat Jun 12 19:48:33 2010 New Revision: 75337 Added: pypy/trunk/pypy/module/cpyext/cdatetime.py - copied unchanged from r75334, pypy/trunk/pypy/module/cpyext/datetime.py Removed: pypy/trunk/pypy/module/cpyext/datetime.py Modified: pypy/trunk/pypy/module/cpyext/__init__.py pypy/trunk/pypy/module/cpyext/api.py Log: Rename datetime to cdatetime to avoid nameclashes with builtin python module Modified: pypy/trunk/pypy/module/cpyext/__init__.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/__init__.py (original) +++ pypy/trunk/pypy/module/cpyext/__init__.py Sat Jun 12 19:48:33 2010 @@ -64,7 +64,7 @@ import pypy.module.cpyext.sliceobject import pypy.module.cpyext.stubsactive import pypy.module.cpyext.pystate -import pypy.module.cpyext.datetime +import pypy.module.cpyext.cdatetime import pypy.module.cpyext.complexobject import pypy.module.cpyext.weakrefobject import pypy.module.cpyext.funcobject Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Sat Jun 12 19:48:33 2010 @@ -315,7 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), - 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.cdatetime.build_datetime_api(space)'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -361,7 +361,7 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - from pypy.module.cpyext.datetime import PyDateTime_CAPI + from pypy.module.cpyext.cdatetime import PyDateTime_CAPI return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] From fijal at codespeak.net Sat Jun 12 21:09:05 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 21:09:05 +0200 (CEST) Subject: [pypy-svn] r75338 - in pypy/trunk/pypy/tool: . test Message-ID: <20100612190905.6D7D336C221@codespeak.net> Author: fijal Date: Sat Jun 12 21:08:20 2010 New Revision: 75338 Added: pypy/trunk/pypy/tool/pack.py (contents, props changed) pypy/trunk/pypy/tool/test/test_pack.py Log: A tool for packaging pypy in a platform-independent way Added: pypy/trunk/pypy/tool/pack.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/pack.py Sat Jun 12 21:08:20 2010 @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import autopath +import sys +import tarfile +import os, py + +goal_dir = py.path.local(__file__).join('..', '..', 'translator', 'goal') + +def filenames_from_platform(platform): + if platform == 'win32': + files = [goal_dir / 'pypy-c.exe'] + dll = goal_dir.join('pypy-c.dll') + if dll.check(): + files.append(dll) + else: + files = [goal_dir / 'pypy-c'] + for file in files: + if not file.check(): + print "Necessary file (%s) missing, build pypy" % file + sys.exit(1) + return files + +def main(outbasename='pypy-c.tar.bz2'): + files = filenames_from_platform(sys.platform) + olddir = os.getcwd() + os.chdir(str(goal_dir)) + try: + t = tarfile.open(str(goal_dir.join(outbasename)), 'w:bz2') + for f in files: + t.add(f.basename) + t.close() + finally: + os.chdir(olddir) + +if __name__ == '__main__': + main() Added: pypy/trunk/pypy/tool/test/test_pack.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/test/test_pack.py Sat Jun 12 21:08:20 2010 @@ -0,0 +1,24 @@ + +import py, sys +from pypy.tool.pack import main +import tarfile + +def test_pack(): + goal_dir = py.path.local(__file__).join('..', '..', '..', 'translator', 'goal') + if not sys.platform == 'linux2': + py.test.skip("untested on not linux") + pypy_c = goal_dir.join('pypy-c') + if not pypy_c.check(): + pypy_c.write('xxx') + remove_pypy_c = True + else: + remove_pypy_c = False + try: + main() + finally: + if remove_pypy_c: + pypy_c.remove() + bzfile = goal_dir.join('pypy-c.tar.bz2') + assert bzfile.check() + assert tarfile.open(str(bzfile), 'r:bz2').getnames() == ['pypy-c'] + bzfile.remove() From fijal at codespeak.net Sat Jun 12 21:10:51 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 21:10:51 +0200 (CEST) Subject: [pypy-svn] r75339 - pypy/build/bot2/pypybuildbot Message-ID: <20100612191051.2590C282B9C@codespeak.net> Author: fijal Date: Sat Jun 12 21:10:38 2010 New Revision: 75339 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Simplify building process by using external tool Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sat Jun 12 21:10:38 2010 @@ -134,17 +134,10 @@ "--resultlog=pypyjit.log", "pypy/module/pypyjit/test"], logfiles={'pytestLog': 'pypyjit.log'})) - if platform != 'win32': - self.addStep(ShellCmd( - description="compress pypy-c", - command=["bzip2", "-kf", "pypy/translator/goal/pypy-c"])) - else: - self.addStep(ShellCmd( - description="compress pypy-c", - command=["python", "-c", "from bz2 import BZ2File; " - "BZ2File('pypy/translator/goal/pypy-c.bz2', 'w')" - ".write(open('pypy/translator/goal/pypy-c.exe'" - ", 'rb').read())"])) + self.addStep(ShellCmd( + description="compress pypy-c", + command=["python", "pack.py"], + workdir='build/pypy/tool')) if pypyjit: kind = 'jit' else: From fijal at codespeak.net Sat Jun 12 22:28:03 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:28:03 +0200 (CEST) Subject: [pypy-svn] r75340 - pypy/build/bot2/pypybuildbot Message-ID: <20100612202803.E58A5282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:28:02 2010 New Revision: 75340 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Ooops, now that we make tar archives, adapt. Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sat Jun 12 22:28:02 2010 @@ -147,14 +147,13 @@ kind = 'nojit' nightly = '~/nightly/' name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + '.bz2' - pypy_c_rel = 'build/pypy/translator/goal/pypy-c.bz2' + pypy_c_rel = 'build/pypy/translator/goal/pypy-c.tar.bz2' self.addStep(PyPyUpload(slavesrc=pypy_c_rel, masterdest=WithProperties(nightly), basename=name, workdir='.', blocksize=100*1024)) - class JITBenchmark(factory.BuildFactory): def __init__(self, platform='linux'): factory.BuildFactory.__init__(self) From fijal at codespeak.net Sat Jun 12 22:31:10 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:31:10 +0200 (CEST) Subject: [pypy-svn] r75341 - pypy/release/1.3.x/pypy/config Message-ID: <20100612203110.45224282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:31:08 2010 New Revision: 75341 Modified: pypy/release/1.3.x/pypy/config/translationoption.py Log: On release builds, disable JIT debug Modified: pypy/release/1.3.x/pypy/config/translationoption.py ============================================================================== --- pypy/release/1.3.x/pypy/config/translationoption.py (original) +++ pypy/release/1.3.x/pypy/config/translationoption.py Sat Jun 12 22:31:08 2010 @@ -112,7 +112,7 @@ default="auto", cmdline="--jit-backend"), ChoiceOption("jit_debug", "the amount of debugging dumps made by the JIT", ["off", "profile", "steps", "detailed"], - default="profile", # XXX for now + default="off", cmdline="--jit-debug"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], From fijal at codespeak.net Sat Jun 12 22:40:18 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:40:18 +0200 (CEST) Subject: [pypy-svn] r75342 - in pypy/trunk/pypy/tool/release: . test Message-ID: <20100612204018.41C48282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:40:16 2010 New Revision: 75342 Added: pypy/trunk/pypy/tool/release/ pypy/trunk/pypy/tool/release/__init__.py pypy/trunk/pypy/tool/release/autopath.py - copied unchanged from r75334, pypy/trunk/pypy/tool/autopath.py pypy/trunk/pypy/tool/release/pack.py - copied, changed from r75338, pypy/trunk/pypy/tool/pack.py pypy/trunk/pypy/tool/release/test/ pypy/trunk/pypy/tool/release/test/__init__.py pypy/trunk/pypy/tool/release/test/test_pack.py - copied, changed from r75338, pypy/trunk/pypy/tool/test/test_pack.py Log: Move pack to it's own directory (would contain more stuff at the end) Added: pypy/trunk/pypy/tool/release/__init__.py ============================================================================== Copied: pypy/trunk/pypy/tool/release/pack.py (from r75338, pypy/trunk/pypy/tool/pack.py) ============================================================================== --- pypy/trunk/pypy/tool/pack.py (original) +++ pypy/trunk/pypy/tool/release/pack.py Sat Jun 12 22:40:16 2010 @@ -5,7 +5,7 @@ import tarfile import os, py -goal_dir = py.path.local(__file__).join('..', '..', 'translator', 'goal') +goal_dir = py.path.local(__file__).join('..', '..', '..', 'translator', 'goal') def filenames_from_platform(platform): if platform == 'win32': Added: pypy/trunk/pypy/tool/release/test/__init__.py ============================================================================== Copied: pypy/trunk/pypy/tool/release/test/test_pack.py (from r75338, pypy/trunk/pypy/tool/test/test_pack.py) ============================================================================== --- pypy/trunk/pypy/tool/test/test_pack.py (original) +++ pypy/trunk/pypy/tool/release/test/test_pack.py Sat Jun 12 22:40:16 2010 @@ -1,10 +1,9 @@ import py, sys -from pypy.tool.pack import main +from pypy.tool.release.pack import main, goal_dir import tarfile def test_pack(): - goal_dir = py.path.local(__file__).join('..', '..', '..', 'translator', 'goal') if not sys.platform == 'linux2': py.test.skip("untested on not linux") pypy_c = goal_dir.join('pypy-c') From fijal at codespeak.net Sat Jun 12 22:40:32 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:40:32 +0200 (CEST) Subject: [pypy-svn] r75343 - in pypy/trunk/pypy/tool: . test Message-ID: <20100612204032.70C38282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:40:31 2010 New Revision: 75343 Removed: pypy/trunk/pypy/tool/pack.py pypy/trunk/pypy/tool/test/test_pack.py Log: Part of the previous checkin From fijal at codespeak.net Sat Jun 12 22:41:26 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:41:26 +0200 (CEST) Subject: [pypy-svn] r75344 - pypy/build/bot2/pypybuildbot Message-ID: <20100612204126.9B87C282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:41:25 2010 New Revision: 75344 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: update buildbot Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sat Jun 12 22:41:25 2010 @@ -137,7 +137,7 @@ self.addStep(ShellCmd( description="compress pypy-c", command=["python", "pack.py"], - workdir='build/pypy/tool')) + workdir='build/pypy/tool/release')) if pypyjit: kind = 'jit' else: From fijal at codespeak.net Sat Jun 12 22:49:06 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:49:06 +0200 (CEST) Subject: [pypy-svn] r75345 - pypy/trunk/pypy/tool/release Message-ID: <20100612204906.B995636C374@codespeak.net> Author: fijal Date: Sat Jun 12 22:49:04 2010 New Revision: 75345 Added: pypy/trunk/pypy/tool/release/force-builds.py (contents, props changed) Log: Add a tool stolen from twistedmatrix.com by exarkun (thx) Added: pypy/trunk/pypy/tool/release/force-builds.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/release/force-builds.py Sat Jun 12 22:49:04 2010 @@ -0,0 +1,63 @@ +#!/usr/bin/python + +""" +Force the PyPy buildmaster to run a builds on all builders that produce +nightly builds for a particular branch. + +Taken from http://twistedmatrix.com/trac/browser/sandbox/exarkun/force-builds.py + +modified by PyPy team +""" + +import os, sys, pwd, urllib + +from twisted.internet import reactor, defer +from twisted.python import log +from twisted.web import client +from twisted.web.error import PageRedirect + +BUILDERS = [ + 'pypy-c-app-level-linux-x86-32', + 'pypy-c-app-level-linux-64', + 'pypy-c-stackless-app-level-linux-x86-32', + 'pypy-c-app-level-win-32', + 'pypy-c-jit-linux-x86-32', + 'pypy-c-jit-macosx-x86-32', + 'pypy-c-jit-win-x86-32', +] + +def main(): + branch = sys.argv[1] + if (not branch.startswith('/branch/') and not branch.startswith('/tag/') and + not branch.startswith('/release/')): + branch = '/branch/' + branch + + lock = defer.DeferredLock() + requests = [] + def ebList(err): + if err.check(PageRedirect) is not None: + return None + log.err(err, "Build force failure") + + for builder in BUILDERS: + print 'Forcing', builder, '...' + url = "http://buildbot.pypy.org/builders/" + builder + "/force" + args = [ + ('username', pwd.getpwuid(os.getuid())[0]), + ('revision', ''), + ('submit', 'Force Build'), + ('branch', branch), + ('comments', "Forced by command line script")] + url = url + '?' + '&'.join([k + '=' + urllib.quote(v) for (k, v) in args]) + requests.append( + lock.run(client.getPage, url, followRedirect=False).addErrback(ebList)) + + d = defer.gatherResults(requests) + d.addErrback(log.err) + d.addCallback(lambda ign: reactor.stop()) + reactor.run() + print 'See http://buildbot.pypy.org/summary after a while' + +if __name__ == '__main__': + log.startLogging(sys.stdout) + main() From fijal at codespeak.net Sat Jun 12 22:51:19 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 22:51:19 +0200 (CEST) Subject: [pypy-svn] r75346 - pypy/trunk/pypy/doc/play1 Message-ID: <20100612205119.D57E7282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 22:51:18 2010 New Revision: 75346 Removed: pypy/trunk/pypy/doc/play1/ Log: I don't think those docs are of any use any more From fijal at codespeak.net Sat Jun 12 23:17:36 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 23:17:36 +0200 (CEST) Subject: [pypy-svn] r75347 - pypy/release/1.3.x/pypy/module/sys Message-ID: <20100612211736.31B3E282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 23:17:35 2010 New Revision: 75347 Modified: pypy/release/1.3.x/pypy/module/sys/version.py Log: Bump pypy version Modified: pypy/release/1.3.x/pypy/module/sys/version.py ============================================================================== --- pypy/release/1.3.x/pypy/module/sys/version.py (original) +++ pypy/release/1.3.x/pypy/module/sys/version.py Sat Jun 12 23:17:35 2010 @@ -7,7 +7,7 @@ CPYTHON_VERSION = (2, 5, 2, "beta", 42) CPYTHON_API_VERSION = 1012 -PYPY_VERSION = (1, 2, 0, "beta", '?') +PYPY_VERSION = (1, 3, 0, "beta", '?') # the last item is replaced by the svn revision ^^^ TRIM_URL_UP_TO = 'svn/pypy/' From fijal at codespeak.net Sat Jun 12 23:24:55 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 23:24:55 +0200 (CEST) Subject: [pypy-svn] r75348 - pypy/trunk/pypy/doc Message-ID: <20100612212455.75A0C282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 23:24:54 2010 New Revision: 75348 Modified: pypy/trunk/pypy/doc/how-to-release.txt Log: Update this file. I think that's fine for now Modified: pypy/trunk/pypy/doc/how-to-release.txt ============================================================================== --- pypy/trunk/pypy/doc/how-to-release.txt (original) +++ pypy/trunk/pypy/doc/how-to-release.txt Sat Jun 12 23:24:54 2010 @@ -4,12 +4,13 @@ Overview --------- -As a meta rule setting up issues in the tracker for items here may help not forgetting things. -A set of todo files may also work. +As a meta rule setting up issues in the tracker for items here may help not +forgetting things. A set of todo files may also work. Check and prioritize all issues for the release, postpone some if necessary, -create new issues also as necessary. A meeting (or meetings) should be organized -to decide what things are priorities, should go in and work for the release. +create new issues also as necessary. A meeting (or meetings) should be +organized to decide what things are priorities, should go in and work for +the release. An important thing is to get the documentation into an up-to-date state! @@ -25,34 +26,21 @@ necessary * update pypy/doc/contributor.txt (and possibly LICENSE) * update README -* update pypy.org (under extradoc/pypy.org), rebuild and commit -* build following binaries (supported versions for now): - JIT: windows, linux, os/x - no JIT: windows, linux, os/x - sandbox: linux, os/x - stackless: windows, linux, os/x +* go to pypy/tool/release and run: + force-builds.py /release/ +* wait for builds to complete, make sure there are no failures +* run pypy/tool/release/make_release.py, this will build necessary binaries + and upload them to pypy.org + + Following binaries should be built, however, we need more buildbots: + JIT: windows, linux, os/x + no JIT: windows, linux, os/x + sandbox: linux, os/x + stackless: windows, linux, os/x -XXX stuff below is out-of-date or at least needs some review * write release announcement pypy/doc/release-x.y(.z).txt the release announcement should contain a direct link to the download page -* update pypy/doc/getting-started.txt links at the top - and release number references, make sure it is generally up-to-date -* use, after the necessary updates, pypy/tool/makerelease.py to - make the tarballs on codespeak; this generates html doc for the - tarballs too. Use:: - - makerelease -tag .z pypy-x.y.z - - to tag and produce final tarballs. Without the '-tag' this can - be used to make pre-release testing tarballs. -* nowadays we have an extensive set of nightly builds and test - runs. Is probably good to do some minimal testing of the tarballs, - especially to check that things work even outside a working copy or - if some stuff is missing. We have some support for running part of - our nightly tests on tarballs (see - http://codespeak.net/svn/user/pedronis/tarball-testing). -* write a news item for the release in pypy/doc/news.txt -* update http://codespeak.net/svn/pypy/dist and codespeak's - precomputed html files -* send announcements to pypy-dev, pypy-funding, python-list, +* update pypy.org (under extradoc/pypy.org), rebuild and commit +* post announcement on morepypy.blogspot.com +* send announcements to pypy-dev, python-list, python-announce, python-dev ... From fijal at codespeak.net Sat Jun 12 23:31:41 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 23:31:41 +0200 (CEST) Subject: [pypy-svn] r75349 - pypy/trunk/pypy/doc Message-ID: <20100612213141.E0236282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 23:31:40 2010 New Revision: 75349 Added: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Start writing an announcement Added: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Sat Jun 12 23:31:40 2010 @@ -0,0 +1,23 @@ +======================= +PyPy 1.3: Stabilization +======================= + +Hello. + +We're please to announce release of PyPy 1.3. This release has two major +points. First of all, we stabilized status of JIT compiler after 1.2 +release, answering user issues, fixing bugs and generally improving speed. + +On the other hand, we're pleased to announce alpha support for loading +CPython extension modules written in C. While the main point of the release +is increased stability, this part is in alpha stage and as is, it's not suited +for production environment. + +Highlight of this release +========================= + +XXX a rough list +- cpyext +- bugfixes +- blackhole-improvements +- minor jit improvements From agaynor at codespeak.net Sat Jun 12 23:36:07 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Sat, 12 Jun 2010 23:36:07 +0200 (CEST) Subject: [pypy-svn] r75350 - pypy/trunk/pypy/doc Message-ID: <20100612213607.6BD43282BD8@codespeak.net> Author: agaynor Date: Sat Jun 12 23:36:05 2010 New Revision: 75350 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: A few cleanups to the release notes. Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Sat Jun 12 23:36:05 2010 @@ -5,13 +5,13 @@ Hello. We're please to announce release of PyPy 1.3. This release has two major -points. First of all, we stabilized status of JIT compiler after 1.2 -release, answering user issues, fixing bugs and generally improving speed. +points. First of all, we stabilized the JIT compiler since 1.2 release, +answered user issues, fixed bugs and generally improved speed. On the other hand, we're pleased to announce alpha support for loading CPython extension modules written in C. While the main point of the release -is increased stability, this part is in alpha stage and as is, it's not suited -for production environment. +is increased stability, this part is in alpha stage and it is not yet suited +for production environments. Highlight of this release ========================= From fijal at codespeak.net Sat Jun 12 23:55:22 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jun 2010 23:55:22 +0200 (CEST) Subject: [pypy-svn] r75351 - in pypy/release/1.3.x: . pypy/jit/backend pypy/jit/backend/x86 pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/test pypy/module/cpyext/include pypy/translator/c/src pypy/translator/platform pypy/translator/platform/test pypy/translator/tool pypy/translator/tool/test Message-ID: <20100612215522.028A5282BD8@codespeak.net> Author: fijal Date: Sat Jun 12 23:55:19 2010 New Revision: 75351 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/jit/backend/model.py pypy/release/1.3.x/pypy/jit/backend/x86/assembler.py pypy/release/1.3.x/pypy/jit/backend/x86/regalloc.py pypy/release/1.3.x/pypy/jit/codewriter/jtransform.py pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py pypy/release/1.3.x/pypy/jit/codewriter/test/test_jtransform.py pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py pypy/release/1.3.x/pypy/jit/metainterp/virtualizable.py pypy/release/1.3.x/pypy/jit/metainterp/warmspot.py pypy/release/1.3.x/pypy/module/cpyext/include/modsupport.inl pypy/release/1.3.x/pypy/translator/c/src/commondefs.h pypy/release/1.3.x/pypy/translator/platform/__init__.py pypy/release/1.3.x/pypy/translator/platform/darwin.py pypy/release/1.3.x/pypy/translator/platform/posix.py pypy/release/1.3.x/pypy/translator/platform/test/test_platform.py pypy/release/1.3.x/pypy/translator/platform/windows.py pypy/release/1.3.x/pypy/translator/tool/cbuild.py pypy/release/1.3.x/pypy/translator/tool/test/test_cbuild.py Log: Merge from trunk. Revisions: 75257,75259,75260,75267,75269,75279,75279,75287,75288,75289,75293 Modified: pypy/release/1.3.x/pypy/jit/backend/model.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/model.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/model.py Sat Jun 12 23:55:19 2010 @@ -7,7 +7,10 @@ # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] Modified: pypy/release/1.3.x/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/x86/assembler.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/x86/assembler.py Sat Jun 12 23:55:19 2010 @@ -1364,28 +1364,79 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + mc.JMP(rel8_patched_later) # done jmp_location = mc.get_relative_pos() + # + # Path B: fast path. Must load the return value, and reset the token offset = jmp_location - je_location assert 0 < offset <= 127 mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + # + # Reset the vable token --- XXX really too much special logic here:-( + if self.cpu.index_of_virtualizable >= 0: + from pypy.jit.backend.llsupport.descr import BaseFieldDescr + fielddescr = self.cpu.vable_token_descr + assert isinstance(fielddescr, BaseFieldDescr) + ofs = fielddescr.offset + mc.MOV(eax, arglocs[1]) + mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + # in the line above, TOKEN_NONE = 0 + # + if op.result is not None: + # load the return value from fail_boxes_xxx[0] + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location - assert 0 < offset <= 127 + assert 0 <= offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/release/1.3.x/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/x86/regalloc.py Sat Jun 12 23:55:19 2010 @@ -640,7 +640,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: Modified: pypy/release/1.3.x/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/jtransform.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/jtransform.py Sat Jun 12 23:55:19 2010 @@ -190,6 +190,10 @@ 'int_le': 'int_ge', 'int_gt': 'int_lt', 'int_ge': 'int_le', + 'uint_lt': 'uint_gt', + 'uint_le': 'uint_ge', + 'uint_gt': 'uint_lt', + 'uint_ge': 'uint_le', 'float_lt': 'float_gt', 'float_le': 'float_ge', 'float_gt': 'float_lt', @@ -210,6 +214,10 @@ rewrite_op_int_le = _rewrite_symmetric rewrite_op_int_gt = _rewrite_symmetric rewrite_op_int_ge = _rewrite_symmetric + rewrite_op_uint_lt = _rewrite_symmetric + rewrite_op_uint_le = _rewrite_symmetric + rewrite_op_uint_gt = _rewrite_symmetric + rewrite_op_uint_ge = _rewrite_symmetric rewrite_op_float_add = _rewrite_symmetric rewrite_op_float_mul = _rewrite_symmetric @@ -703,20 +711,11 @@ ('uint_add', 'int_add'), ('uint_sub', 'int_sub'), ('uint_mul', 'int_mul'), - ('uint_floordiv', 'int_floordiv'), - ('uint_floordiv_zer', 'int_floordiv_zer'), - ('uint_mod', 'int_mod'), - ('uint_mod_zer', 'int_mod_zer'), - ('uint_lt', 'int_lt'), - ('uint_le', 'int_le'), ('uint_eq', 'int_eq'), ('uint_ne', 'int_ne'), - ('uint_gt', 'int_gt'), - ('uint_ge', 'int_ge'), ('uint_and', 'int_and'), ('uint_or', 'int_or'), ('uint_lshift', 'int_lshift'), - ('uint_rshift', 'int_rshift'), ('uint_xor', 'int_xor'), ]: assert _old not in locals() Modified: pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py Sat Jun 12 23:55:19 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import lltype, rclass, rstr from pypy.objspace.flow.model import SpaceOperation, Variable, Constant from pypy.translator.unsimplify import varoftype -from pypy.rlib.rarithmetic import ovfcheck +from pypy.rlib.rarithmetic import ovfcheck, r_uint from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver from pypy.rlib.objectmodel import keepalive_until_here from pypy.rlib import jit @@ -705,3 +705,13 @@ int_add %i1, %i2 -> %i3 int_return %i3 """, transform=True) + + def test_uint_operations(self): + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + self.encoding_test(f, [200], """ + int_sub %i0, $123L -> %i1 + uint_rshift %i1, $1L -> %i2 + uint_le %i2, $456L -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/release/1.3.x/pypy/jit/codewriter/test/test_jtransform.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/test/test_jtransform.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/test/test_jtransform.py Sat Jun 12 23:55:19 2010 @@ -150,7 +150,8 @@ ops = {'int_add': 'int_add', 'int_or': 'int_or', 'int_gt': ('int_gt', 'int_lt'), - 'uint_le': ('int_le', 'int_ge'), + 'uint_eq': 'int_eq', + 'uint_le': ('uint_le', 'uint_ge'), 'char_ne': 'int_ne', 'char_lt': ('int_lt', 'int_gt'), 'uint_xor': 'int_xor', Modified: pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py Sat Jun 12 23:55:19 2010 @@ -1102,9 +1102,6 @@ self._addr2name_values = [] self.__dict__.update(compile.make_done_loop_tokens()) - # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) def _freeze_(self): return True @@ -1147,6 +1144,12 @@ RESULT = codewriter.portal_graph.getreturnvar().concretetype self.result_type = history.getkind(RESULT) # + # store this information for fastpath of call_assembler + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args Modified: pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py Sat Jun 12 23:55:19 2010 @@ -233,8 +233,8 @@ b = r_uint(b) return a/b - res = self.interp_operations(f, [4, 3]) - assert res == 1 + res = self.interp_operations(f, [-4, 3]) + assert res == long(r_uint(-4)) // 3 def test_direct_call(self): def g(n): @@ -538,6 +538,29 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_uint_operations(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + res = self.interp_operations(f, [50]) + assert res == False + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + + def test_uint_condition(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + if ((r_uint(n) - 123) >> 1) <= r_uint(456): + return 24 + else: + return 12 + res = self.interp_operations(f, [50]) + assert res == 12 + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + def test_getfield(self): class A: pass Modified: pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py Sat Jun 12 23:55:19 2010 @@ -1,6 +1,7 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint -from pypy.rlib.jit import unroll_safe +from pypy.rlib.jit import unroll_safe, dont_look_inside +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr @@ -750,6 +751,60 @@ res = self.meta_interp(main, [0], inline=True) assert res == main(0) + def test_directly_call_assembler_virtualizable_reset_token(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rlib.debug import llinterpcall + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno : str(codeno), + can_inline = lambda codeno : False) + + @dont_look_inside + def check_frame(subframe): + if we_are_translated(): + llinterpcall(lltype.Void, check_ll_frame, subframe) + def check_ll_frame(ll_subframe): + # This is called with the low-level Struct that is the frame. + # Check that the vable_token was correctly reset to zero. + # Note that in order for that test to catch failures, it needs + # three levels of recursion: the vable_token of the subframe + # at the level 2 is set to a non-zero value when doing the + # call to the level 3 only. This used to fail when the test + # is run via pypy.jit.backend.x86.test.test_recursive. + assert ll_subframe.vable_token == 0 + + def main(codeno): + frame = Frame() + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 5: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno < 2: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(codeno + 1, subframe) + check_frame(subframe) + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + res = self.meta_interp(main, [0], inline=True) + assert res == main(0) + def test_directly_call_assembler_virtualizable_force(self): class Thing(object): def __init__(self, val): Modified: pypy/release/1.3.x/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/virtualizable.py Sat Jun 12 23:55:19 2010 @@ -11,7 +11,7 @@ class VirtualizableInfo: - TOKEN_NONE = 0 + TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 def __init__(self, warmrunnerdesc): Modified: pypy/release/1.3.x/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/warmspot.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/warmspot.py Sat Jun 12 23:55:19 2010 @@ -604,8 +604,10 @@ if vinfo is not None: self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) + self.cpu.vable_token_descr = vinfo.vable_token_descr else: self.cpu.index_of_virtualizable = -1 + self.cpu.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr Modified: pypy/release/1.3.x/pypy/module/cpyext/include/modsupport.inl ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/include/modsupport.inl (original) +++ pypy/release/1.3.x/pypy/module/cpyext/include/modsupport.inl Sat Jun 12 23:55:19 2010 @@ -7,12 +7,20 @@ extern "C" { #endif +#ifdef PYPY_STANDALONE +/* XXX1 On translation, forwarddecl.h is included after this file */ +/* XXX2 genc.py transforms "const char*" into "char*" */ +extern PyObject *_Py_InitPyPyModule(char *, PyMethodDef *, char *, PyObject *, int); +#endif + Py_LOCAL_INLINE(PyObject *) Py_InitModule4( const char* name, PyMethodDef* methods, const char* doc, PyObject *self, int api_version) { - return _Py_InitPyPyModule(name, methods, doc, self, api_version); + return _Py_InitPyPyModule((char*)name, methods, + (char*)doc, self, + api_version); } #ifdef __cplusplus Modified: pypy/release/1.3.x/pypy/translator/c/src/commondefs.h ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/src/commondefs.h (original) +++ pypy/release/1.3.x/pypy/translator/c/src/commondefs.h Sat Jun 12 23:55:19 2010 @@ -82,5 +82,7 @@ #define Py_HUGE_VAL HUGE_VAL #ifdef _WIN32 +#ifndef MS_WINDOWS # define MS_WINDOWS /* a synonym */ #endif +#endif Modified: pypy/release/1.3.x/pypy/translator/platform/__init__.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/__init__.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/__init__.py Sat Jun 12 23:55:19 2010 @@ -5,6 +5,7 @@ import sys, py, os +from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_log log = py.log.Producer("platform") py.log.setconsumer("platform", ansi_log) @@ -62,9 +63,20 @@ def execute(self, executable, args=None, env=None, compilation_info=None): if env is None: env = os.environ.copy() - if compilation_info is not None: + else: + env = env.copy() + + # On Windows, %SystemRoot% must be present for most programs to start + if (os.name == 'nt' and + "SystemRoot" not in env and + "SystemRoot" in os.environ): + env["SystemRoot"] = os.environ["SystemRoot"] + + # Set LD_LIBRARY_PATH on posix platforms + if os.name == 'posix' and compilation_info is not None: env['LD_LIBRARY_PATH'] = ':'.join( [str(i) for i in compilation_info.library_dirs]) + returncode, stdout, stderr = _run_subprocess(str(executable), args, env) return ExecutionResult(returncode, stdout, stderr) @@ -112,6 +124,18 @@ for line in stderr.splitlines(): log.WARNING(line) + def _make_response_file(self, prefix): + """Creates a temporary file with the specified prefix, + and returns its name""" + # Build unique filename + num = 0 + while 1: + response_file = udir.join('%s%i' % (prefix, num)) + num += 1 + if not response_file.check(): + break + return response_file + def _preprocess_include_dirs(self, include_dirs): return include_dirs @@ -133,9 +157,15 @@ library_dirs = self._libdirs(library_dirs) libraries = self._libs(eci.libraries) link_files = self._linkfiles(eci.link_files) - return (library_dirs + self.link_flags + + export_flags = self._exportsymbols_link_flags(eci) + return (library_dirs + self.link_flags + export_flags + link_files + list(eci.link_extra) + libraries) + def _exportsymbols_link_flags(self, eci): + if eci.export_symbols: + raise ValueError("This platform does not support export symbols") + return [] + def _finish_linking(self, ofiles, eci, outputfilename, standalone): if outputfilename is None: outputfilename = ofiles[0].purebasename Modified: pypy/release/1.3.x/pypy/translator/platform/darwin.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/darwin.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/darwin.py Sat Jun 12 23:55:19 2010 @@ -56,6 +56,17 @@ include_dirs = self._includedirs(eci.include_dirs) return (args + frameworks + include_dirs) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("_%s\n" % (sym,)) + f.close() + return ["-Wl,-exported_symbols_list,%s" % (response_file,)] + class Darwin_i386(Darwin): name = "darwin_i386" link_flags = ['-arch', 'i386', '-mmacosx-version-min=10.4'] Modified: pypy/release/1.3.x/pypy/translator/platform/posix.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/posix.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/posix.py Sat Jun 12 23:55:19 2010 @@ -37,9 +37,21 @@ return oname def _link_args_from_eci(self, eci, standalone): - eci = eci.convert_exportsymbols_to_file() return Platform._link_args_from_eci(self, eci, standalone) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + f.write("{\n") + for sym in eci.export_symbols: + f.write("%s;\n" % (sym,)) + f.write("};") + f.close() + return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] + def _link(self, cc, ofiles, link_args, standalone, exe_name): args = [str(ofile) for ofile in ofiles] + link_args args += ['-o', str(exe_name)] @@ -61,7 +73,6 @@ def gen_makefile(self, cfiles, eci, exe_name=None, path=None, shared=False): - eci = eci.convert_exportsymbols_to_file() cfiles = [py.path.local(f) for f in cfiles] cfiles += [py.path.local(f) for f in eci.separate_module_files] @@ -73,10 +84,12 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + linkflags += self._exportsymbols_link_flags(eci) + if shared: libname = exe_name.new(ext='').basename target_name = 'lib' + exe_name.new(ext=self.so_ext).basename Modified: pypy/release/1.3.x/pypy/translator/platform/test/test_platform.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/test/test_platform.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/test/test_platform.py Sat Jun 12 23:55:19 2010 @@ -113,7 +113,7 @@ def test_environment_inheritance(self): # make sure that environment is inherited cmd = 'import os; print os.environ["_SOME_VARIABLE_%d"]' - res = self.platform.execute('python', ['-c', cmd % 1], + res = self.platform.execute(sys.executable, ['-c', cmd % 1], env={'_SOME_VARIABLE_1':'xyz'}) assert 'xyz' in res.out os.environ['_SOME_VARIABLE_2'] = 'zyz' Modified: pypy/release/1.3.x/pypy/translator/platform/windows.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/windows.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/windows.py Sat Jun 12 23:55:19 2010 @@ -139,8 +139,18 @@ def _link_args_from_eci(self, eci, standalone): # Windows needs to resolve all symbols even for DLLs - args = super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) - return args + ['/EXPORT:%s' % symbol for symbol in eci.export_symbols] + return super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) + + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("exported_symbols_") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("/EXPORT:%s\n" % (sym,)) + f.close() + return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): oname = cfile.new(ext='obj') @@ -179,7 +189,7 @@ # Microsoft compilers write compilation errors to stdout stderr = stdout + stderr errorfile = outname.new(ext='errors') - errorfile.write(stderr) + errorfile.write(stderr, mode='wb') stderrlines = stderr.splitlines() for line in stderrlines: log.ERROR(line) @@ -203,10 +213,11 @@ m.exe_name = exe_name m.eci = eci - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + [ '/EXPORT:$(PYPY_MAIN_FUNCTION)'] + linkflags += self._exportsymbols_link_flags(eci) if shared: so_name = exe_name.new(ext=self.so_ext) @@ -243,6 +254,7 @@ ('LDFLAGSEXTRA', list(eci.link_extra)), ('CC', self.cc), ('CC_LINK', self.link), + ('LINKFILES', eci.link_files), ('MASM', self.masm), ] @@ -262,12 +274,13 @@ '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS)') else: m.rule('$(TARGET)', '$(OBJECTS)', - ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) if shared: - m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename), + m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename) + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo ' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' Modified: pypy/release/1.3.x/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/tool/cbuild.py (original) +++ pypy/release/1.3.x/pypy/translator/tool/cbuild.py Sat Jun 12 23:55:19 2010 @@ -260,34 +260,6 @@ d['separate_module_files'] += tuple(files) return ExternalCompilationInfo(**d) - def convert_exportsymbols_to_file(self): - if not self.export_symbols: - return self - num = 0 - while 1: - file_name = udir.join('dynamic-symbols-%i' % num) - num += 1 - if not file_name.check(): - break - - # XXX this logic should be moved to translator/platform/*.py - d = self._copy_attributes() - f = file_name.open("w") - if host.name.startswith('darwin'): - for sym in self.export_symbols: - f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) - else: - f.write("{\n") - for sym in self.export_symbols: - f.write("%s;\n" % (sym,)) - f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) - f.close() - d['export_symbols'] = () - return ExternalCompilationInfo(**d) - - def get_module_files(self): d = self._copy_attributes() files = d['separate_module_files'] Modified: pypy/release/1.3.x/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/release/1.3.x/pypy/translator/tool/test/test_cbuild.py Sat Jun 12 23:55:19 2010 @@ -71,17 +71,6 @@ e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e - def test_convert_sources_to_c_files(self): - eci = ExternalCompilationInfo( - export_symbols=("foo", ) - ) - neweci = eci.convert_exportsymbols_to_file() - le = neweci.link_extra[-1] - assert "foo;" in file(le.rsplit("=", 1)[1]).read() - e = ExternalCompilationInfo() - assert e.convert_exportsymbols_to_file() is e - - def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' From fijal at codespeak.net Sun Jun 13 00:12:36 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 00:12:36 +0200 (CEST) Subject: [pypy-svn] r75352 - in pypy/release/1.3.x/pypy: doc doc/play1 interpreter/test jit/backend/llgraph jit/backend/x86/test jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/test lib/app_test lib/app_test/ctypes_tests module/__builtin__ module/__builtin__/test module/_codecs/test module/_file/test module/cpyext module/cpyext/test module/imp/test module/itertools/test rlib rlib/parsing/test rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gc rpython/numpy/test rpython/ootypesystem rpython/ootypesystem/test rpython/test rpython/tool tool tool/release translator/c translator/c/src translator/c/test Message-ID: <20100612221236.9A3F0282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 00:12:31 2010 New Revision: 75352 Added: pypy/release/1.3.x/pypy/doc/release-1.3.0.txt - copied unchanged from r75351, pypy/trunk/pypy/doc/release-1.3.0.txt pypy/release/1.3.x/pypy/module/cpyext/cdatetime.py - copied unchanged from r75351, pypy/trunk/pypy/module/cpyext/cdatetime.py pypy/release/1.3.x/pypy/tool/release/ - copied from r75351, pypy/trunk/pypy/tool/release/ Removed: pypy/release/1.3.x/pypy/doc/play1/ pypy/release/1.3.x/pypy/module/cpyext/datetime.py Modified: pypy/release/1.3.x/pypy/doc/how-to-release.txt pypy/release/1.3.x/pypy/interpreter/test/test_function.py pypy/release/1.3.x/pypy/jit/backend/llgraph/llimpl.py pypy/release/1.3.x/pypy/jit/backend/x86/test/test_gc_integration.py pypy/release/1.3.x/pypy/jit/backend/x86/test/test_regalloc.py pypy/release/1.3.x/pypy/jit/codewriter/support.py pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py pypy/release/1.3.x/pypy/jit/metainterp/blackhole.py pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py pypy/release/1.3.x/pypy/jit/metainterp/test/test_loop.py pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_unicode.py pypy/release/1.3.x/pypy/lib/app_test/test_functools.py pypy/release/1.3.x/pypy/module/__builtin__/functional.py pypy/release/1.3.x/pypy/module/__builtin__/test/test_classobj.py pypy/release/1.3.x/pypy/module/__builtin__/test/test_functional.py pypy/release/1.3.x/pypy/module/_codecs/test/test_codecs.py pypy/release/1.3.x/pypy/module/_file/test/test_file_extra.py pypy/release/1.3.x/pypy/module/cpyext/__init__.py pypy/release/1.3.x/pypy/module/cpyext/api.py pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py pypy/release/1.3.x/pypy/module/imp/test/test_app.py pypy/release/1.3.x/pypy/module/itertools/test/test_itertools.py pypy/release/1.3.x/pypy/rlib/parsing/test/test_regexparse.py pypy/release/1.3.x/pypy/rlib/rgc.py pypy/release/1.3.x/pypy/rlib/test/test_rbigint.py pypy/release/1.3.x/pypy/rlib/test/test_rmmap.py pypy/release/1.3.x/pypy/rpython/lltypesystem/llarena.py pypy/release/1.3.x/pypy/rpython/lltypesystem/lloperation.py pypy/release/1.3.x/pypy/rpython/lltypesystem/lltype.py pypy/release/1.3.x/pypy/rpython/lltypesystem/opimpl.py pypy/release/1.3.x/pypy/rpython/lltypesystem/rclass.py pypy/release/1.3.x/pypy/rpython/lltypesystem/rffi.py pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_lltype.py pypy/release/1.3.x/pypy/rpython/memory/gc/generation.py pypy/release/1.3.x/pypy/rpython/memory/gc/marksweep.py pypy/release/1.3.x/pypy/rpython/normalizecalls.py pypy/release/1.3.x/pypy/rpython/numpy/test/test_array.py pypy/release/1.3.x/pypy/rpython/ootypesystem/ootype.py pypy/release/1.3.x/pypy/rpython/ootypesystem/rootype.py pypy/release/1.3.x/pypy/rpython/ootypesystem/test/test_oolist.py pypy/release/1.3.x/pypy/rpython/rbuiltin.py pypy/release/1.3.x/pypy/rpython/test/test_llinterp.py pypy/release/1.3.x/pypy/rpython/test/test_rfloat.py pypy/release/1.3.x/pypy/rpython/test/test_rint.py pypy/release/1.3.x/pypy/rpython/test/test_rlist.py pypy/release/1.3.x/pypy/rpython/test/test_rvirtualizable2.py pypy/release/1.3.x/pypy/rpython/tool/rffi_platform.py pypy/release/1.3.x/pypy/tool/sourcetools.py pypy/release/1.3.x/pypy/translator/c/funcgen.py pypy/release/1.3.x/pypy/translator/c/src/int.h pypy/release/1.3.x/pypy/translator/c/test/test_extfunc.py pypy/release/1.3.x/pypy/translator/c/test/test_typed.py Log: Merge from trunk until HEAD Modified: pypy/release/1.3.x/pypy/doc/how-to-release.txt ============================================================================== --- pypy/release/1.3.x/pypy/doc/how-to-release.txt (original) +++ pypy/release/1.3.x/pypy/doc/how-to-release.txt Sun Jun 13 00:12:31 2010 @@ -4,12 +4,13 @@ Overview --------- -As a meta rule setting up issues in the tracker for items here may help not forgetting things. -A set of todo files may also work. +As a meta rule setting up issues in the tracker for items here may help not +forgetting things. A set of todo files may also work. Check and prioritize all issues for the release, postpone some if necessary, -create new issues also as necessary. A meeting (or meetings) should be organized -to decide what things are priorities, should go in and work for the release. +create new issues also as necessary. A meeting (or meetings) should be +organized to decide what things are priorities, should go in and work for +the release. An important thing is to get the documentation into an up-to-date state! @@ -25,34 +26,21 @@ necessary * update pypy/doc/contributor.txt (and possibly LICENSE) * update README -* update pypy.org (under extradoc/pypy.org), rebuild and commit -* build following binaries (supported versions for now): - JIT: windows, linux, os/x - no JIT: windows, linux, os/x - sandbox: linux, os/x - stackless: windows, linux, os/x +* go to pypy/tool/release and run: + force-builds.py /release/ +* wait for builds to complete, make sure there are no failures +* run pypy/tool/release/make_release.py, this will build necessary binaries + and upload them to pypy.org + + Following binaries should be built, however, we need more buildbots: + JIT: windows, linux, os/x + no JIT: windows, linux, os/x + sandbox: linux, os/x + stackless: windows, linux, os/x -XXX stuff below is out-of-date or at least needs some review * write release announcement pypy/doc/release-x.y(.z).txt the release announcement should contain a direct link to the download page -* update pypy/doc/getting-started.txt links at the top - and release number references, make sure it is generally up-to-date -* use, after the necessary updates, pypy/tool/makerelease.py to - make the tarballs on codespeak; this generates html doc for the - tarballs too. Use:: - - makerelease -tag .z pypy-x.y.z - - to tag and produce final tarballs. Without the '-tag' this can - be used to make pre-release testing tarballs. -* nowadays we have an extensive set of nightly builds and test - runs. Is probably good to do some minimal testing of the tarballs, - especially to check that things work even outside a working copy or - if some stuff is missing. We have some support for running part of - our nightly tests on tarballs (see - http://codespeak.net/svn/user/pedronis/tarball-testing). -* write a news item for the release in pypy/doc/news.txt -* update http://codespeak.net/svn/pypy/dist and codespeak's - precomputed html files -* send announcements to pypy-dev, pypy-funding, python-list, +* update pypy.org (under extradoc/pypy.org), rebuild and commit +* post announcement on morepypy.blogspot.com +* send announcements to pypy-dev, python-list, python-announce, python-dev ... Modified: pypy/release/1.3.x/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/release/1.3.x/pypy/interpreter/test/test_function.py (original) +++ pypy/release/1.3.x/pypy/interpreter/test/test_function.py Sun Jun 13 00:12:31 2010 @@ -158,13 +158,6 @@ assert res[0] == 42 assert res[1] == {'something': 23} - def test_kwargs_sets_positional_mixed(self): - def func(arg1, **kw): - return arg1, kw - res = func(arg1=42, something=23) - assert res[0] == 42 - assert res[1] == {'something': 23} - def test_kwargs_sets_positional_twice(self): def func(arg1, **kw): return arg1, kw Modified: pypy/release/1.3.x/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/llgraph/llimpl.py Sun Jun 13 00:12:31 2010 @@ -4,7 +4,6 @@ when executing on top of the llinterpreter. """ -import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel from pypy.jit.metainterp.history import (ConstInt, ConstPtr, Modified: pypy/release/1.3.x/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/x86/test/test_gc_integration.py Sun Jun 13 00:12:31 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.codewriter import heaptracker @@ -22,7 +22,6 @@ from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc from pypy.jit.backend.x86.regalloc import X86RegisterManager, X86FrameManager,\ X86XMMRegisterManager -from pypy.rpython.annlowlevel import llhelper class MockGcRootMap(object): def get_basic_shape(self): Modified: pypy/release/1.3.x/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/release/1.3.x/pypy/jit/backend/x86/test/test_regalloc.py Sun Jun 13 00:12:31 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, LoopToken, BasicFailDescr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache Modified: pypy/release/1.3.x/pypy/jit/codewriter/support.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/support.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/support.py Sun Jun 13 00:12:31 2010 @@ -16,7 +16,6 @@ from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import MixLevelHelperAnnotator -from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.metainterp.typesystem import deref from pypy.rlib import rgc Modified: pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py Sun Jun 13 00:12:31 2010 @@ -715,3 +715,12 @@ uint_le %i2, $456L -> %i3 int_return %i3 """, transform=True) + + def test_int_between(self): + from pypy.rpython.lltypesystem.lloperation import llop + def f(n, m, p): + return llop.int_between(lltype.Bool, n, m, p) + self.encoding_test(f, [5, 6, 7], """ + int_between %i0, %i1, %i2 -> %i3 + int_return %i3 + """, transform=True) Modified: pypy/release/1.3.x/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/blackhole.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/blackhole.py Sun Jun 13 00:12:31 2010 @@ -475,6 +475,9 @@ @arguments("i", returns="i") def bhimpl_int_is_true(a): return bool(a) + @arguments("i", "i", "i", returns="i") + def bhimpl_int_between(a, b, c): + return a <= b < c @arguments("i", "i", returns="i") def bhimpl_uint_lt(a, b): Modified: pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/pyjitpl.py Sun Jun 13 00:12:31 2010 @@ -315,6 +315,16 @@ if value: self.pc = target + @arguments("box", "box", "box") + def opimpl_int_between(self, b1, b2, b3): + b5 = self.execute(rop.INT_SUB, b3, b1) + if isinstance(b5, ConstInt) and b5.getint() == 1: + # the common case of int_between(a, b, a+1) turns into just INT_EQ + return self.execute(rop.INT_EQ, b2, b1) + else: + b4 = self.execute(rop.INT_SUB, b2, b1) + return self.execute(rop.UINT_LT, b4, b5) + @arguments("box", "descr", "orgpc") def opimpl_switch(self, valuebox, switchdict, orgpc): box = self.implement_guard_value(orgpc, valuebox) Modified: pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/test/test_basic.py Sun Jun 13 00:12:31 2010 @@ -145,6 +145,9 @@ def check_operations_history(self, expected=None, **isns): # this can be used after interp_operations + if expected is not None: + expected = dict(expected) + expected['jump'] = 1 self.metainterp.staticdata.stats.check_history(expected, **isns) @@ -561,6 +564,53 @@ int_le=0, uint_le=1, int_sub=1) + def test_int_between(self): + # + def check(arg1, arg2, arg3, expect_result, **expect_operations): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop + loc = locals().copy() + exec py.code.Source(""" + def f(n, m, p): + arg1 = %(arg1)s + arg2 = %(arg2)s + arg3 = %(arg3)s + return llop.int_between(lltype.Bool, arg1, arg2, arg3) + """ % locals()).compile() in loc + res = self.interp_operations(loc['f'], [5, 6, 7]) + assert res == expect_result + self.check_operations_history(expect_operations) + # + check('n', 'm', 'p', True, int_sub=2, uint_lt=1) + check('n', 'p', 'm', False, int_sub=2, uint_lt=1) + # + check('n', 'm', 6, False, int_sub=2, uint_lt=1) + # + check('n', 4, 'p', False, int_sub=2, uint_lt=1) + check('n', 5, 'p', True, int_sub=2, uint_lt=1) + check('n', 8, 'p', False, int_sub=2, uint_lt=1) + # + check('n', 6, 7, True, int_sub=2, uint_lt=1) + # + check(-2, 'n', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'm', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'p', 'm', False, int_sub=2, uint_lt=1) + #check(0, 'n', 'p', True, uint_lt=1) xxx implement me + #check(0, 'm', 'p', True, uint_lt=1) + #check(0, 'p', 'm', False, uint_lt=1) + # + check(2, 'n', 6, True, int_sub=1, uint_lt=1) + check(2, 'm', 6, False, int_sub=1, uint_lt=1) + check(2, 'p', 6, False, int_sub=1, uint_lt=1) + check(5, 'n', 6, True, int_eq=1) # 6 == 5+1 + check(5, 'm', 6, False, int_eq=1) # 6 == 5+1 + # + check(2, 6, 'm', False, int_sub=1, uint_lt=1) + check(2, 6, 'p', True, int_sub=1, uint_lt=1) + # + check(2, 40, 6, False) + check(2, 40, 60, True) + def test_getfield(self): class A: pass Modified: pypy/release/1.3.x/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/test/test_loop.py Sun Jun 13 00:12:31 2010 @@ -2,7 +2,6 @@ from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.objectmodel import compute_hash from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats -from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop Modified: pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/release/1.3.x/pypy/jit/metainterp/test/test_recursive.py Sun Jun 13 00:12:31 2010 @@ -180,7 +180,6 @@ py.test.fail("DID NOT RAISE") def test_guard_failure_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -217,7 +216,6 @@ assert res == 0 def test_guard_failure_and_then_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -261,7 +259,6 @@ assert res == main(1000) def test_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) @@ -307,7 +304,6 @@ # this passes, if the blackholing shortcut for calls is turned off # it fails, it is very delicate in terms of parameters, # bridge/loop creation order - from pypy.rpython.annlowlevel import hlstr def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) Modified: pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py Sun Jun 13 00:12:31 2010 @@ -210,7 +210,7 @@ result = f(byref(c_int(99))) assert not result.contents == 99 - def test_errors(self): + def test_errors_1(self): f = dll._testfunc_p_p f.restype = c_int @@ -305,7 +305,7 @@ assert 13577625587 == f(1000000000000, cb) - def test_errors(self): + def test_errors_2(self): raises(AttributeError, getattr, dll, "_xxx_yyy") raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") Modified: pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_unicode.py ============================================================================== --- pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_unicode.py (original) +++ pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_unicode.py Sun Jun 13 00:12:31 2010 @@ -90,7 +90,7 @@ assert func(u"abc") == "abc" assert func(u"????") == "" - def test_ascii_replace(self): + def test_ascii_replace_2(self): ctypes.set_conversion_mode("ascii", "replace") assert func("abc") == "abc" assert func(u"abc") == "abc" Modified: pypy/release/1.3.x/pypy/lib/app_test/test_functools.py ============================================================================== --- pypy/release/1.3.x/pypy/lib/app_test/test_functools.py (original) +++ pypy/release/1.3.x/pypy/lib/app_test/test_functools.py Sun Jun 13 00:12:31 2010 @@ -31,7 +31,7 @@ p = self.thetype(map, lambda x: x*10) assert p([1,2,3,4]) == [10, 20, 30, 40] - def test_attributes(self): + def test_attributes_1(self): p = self.thetype(capture, 1, 2, a=10, b=20) # attributes should be readable assert p.func == capture @@ -118,7 +118,7 @@ py.test.raises(ZeroDivisionError, self.thetype(f), 1, 0) py.test.raises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): + def test_attributes_2(self): p = self.thetype(hex) try: del p.__dict__ Modified: pypy/release/1.3.x/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/release/1.3.x/pypy/module/__builtin__/functional.py (original) +++ pypy/release/1.3.x/pypy/module/__builtin__/functional.py Sun Jun 13 00:12:31 2010 @@ -187,13 +187,15 @@ cont = False args_w = [space.w_None] * num_iterators for i in range(num_iterators): - try: - args_w[i] = space.next(iterators_w[i]) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - else: - cont = True + if iterators_w[i] is not None: + try: + args_w[i] = space.next(iterators_w[i]) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + iterators_w[i] = None + else: + cont = True if cont: w_args = space.newtuple(args_w) if none_func: Modified: pypy/release/1.3.x/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/release/1.3.x/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/release/1.3.x/pypy/module/__builtin__/test/test_classobj.py Sun Jun 13 00:12:31 2010 @@ -477,7 +477,7 @@ assert a is a1 assert a.l == [1, 2] - def test_cmp(self): + def test_cmp_and_coerce(self): class A: def __coerce__(self, other): return (1, 2) Modified: pypy/release/1.3.x/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/release/1.3.x/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/release/1.3.x/pypy/module/__builtin__/test/test_functional.py Sun Jun 13 00:12:31 2010 @@ -48,16 +48,35 @@ b = [ 2, 3, 4, 5, 6] assert map(None, a, b) == [('1', 2), (2, 3), (3, 4), ('b', 5), (None, 6)] - def test_map_multiply(self): + def test_map_add(self): a = [1, 2, 3, 4] b = [0, 1, 1, 1] - assert map(lambda x, y: x+y, a, b) == [1, 2, 4, 5] + assert map(lambda x, y: x+y, a, b) == [1, 3, 4, 5] - def test_map_multiply(self): + def test_map_first_item(self): a = [1, 2, 3, 4, 5] b = [] assert map(lambda x, y: x, a, b) == a + def test_map_iterables(self): + class A(object): + def __init__(self, n): + self.n = n + def __iter__(self): + return B(self.n) + class B(object): + def __init__(self, n): + self.n = n + def next(self): + self.n -= 1 + if self.n == 0: raise StopIteration + return self.n + result = map(None, A(3), A(8)) + # this also checks that B.next() is not called any more after it + # raised StopIteration once + assert result == [(2, 7), (1, 6), (None, 5), (None, 4), + (None, 3), (None, 2), (None, 1)] + class AppTestZip: def test_one_list(self): assert zip([1,2,3]) == [(1,), (2,), (3,)] Modified: pypy/release/1.3.x/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/release/1.3.x/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/release/1.3.x/pypy/module/_codecs/test/test_codecs.py Sun Jun 13 00:12:31 2010 @@ -373,7 +373,7 @@ decoded = _codecs.unicode_escape_decode(s)[0] assert decoded == '' - def test_charmap_decode(self): + def test_charmap_decode_1(self): import codecs res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab") assert res == (u"ab\ufffd", 3) @@ -525,7 +525,7 @@ def test_charmap_encode(self): assert 'xxx'.encode('charmap') == 'xxx' - def test_charmap_decode(self): + def test_charmap_decode_2(self): assert 'foo'.decode('charmap') == 'foo' def test_utf7_start_end_in_exception(self): Modified: pypy/release/1.3.x/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/release/1.3.x/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/release/1.3.x/pypy/module/_file/test/test_file_extra.py Sun Jun 13 00:12:31 2010 @@ -71,12 +71,6 @@ inputlines = list(self.file) assert inputlines == self.expected_lines - def test_repr(self): - r = repr(self.file) - assert r.find('open file') >= 0 - assert r.find(self.file.name) >= 0 - assert r.find(self.file.mode) >= 0 - def test_isatty(self): assert not self.file.isatty() Modified: pypy/release/1.3.x/pypy/module/cpyext/__init__.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/__init__.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/__init__.py Sun Jun 13 00:12:31 2010 @@ -64,7 +64,7 @@ import pypy.module.cpyext.sliceobject import pypy.module.cpyext.stubsactive import pypy.module.cpyext.pystate -import pypy.module.cpyext.datetime +import pypy.module.cpyext.cdatetime import pypy.module.cpyext.complexobject import pypy.module.cpyext.weakrefobject import pypy.module.cpyext.funcobject Modified: pypy/release/1.3.x/pypy/module/cpyext/api.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/api.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/api.py Sun Jun 13 00:12:31 2010 @@ -315,7 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), - 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.cdatetime.build_datetime_api(space)'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -361,7 +361,7 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - from pypy.module.cpyext.datetime import PyDateTime_CAPI + from pypy.module.cpyext.cdatetime import PyDateTime_CAPI return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] @@ -801,7 +801,7 @@ if sys.platform == "win32": # '%s' undefined; assuming extern returning int compile_extra.append("/we4013") - else: + elif sys.platform == 'linux2': compile_extra.append("-Werror=implicit-function-declaration") export_symbols_eci.append('pypyAPI') else: Modified: pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py Sun Jun 13 00:12:31 2010 @@ -386,6 +386,7 @@ the latter is added to `sys.modules` for the `"apple.banana"` key. """ # Build the extensions. + import cpyext banana = self.compile_module( "apple.banana", separate_module_files=[self.here + 'banana.c']) self.record_imported_module("apple.banana") Modified: pypy/release/1.3.x/pypy/module/imp/test/test_app.py ============================================================================== --- pypy/release/1.3.x/pypy/module/imp/test/test_app.py (original) +++ pypy/release/1.3.x/pypy/module/imp/test/test_app.py Sun Jun 13 00:12:31 2010 @@ -71,7 +71,8 @@ import test_imp_extra_AUTO1 assert mod is test_imp_extra_AUTO1 - def test_load_module_pyc(self): + def test_load_module_pyc_1(self): + import os fn = self._pyc_file() try: descr = ('.pyc', 'rb', self.imp.PY_COMPILED) @@ -91,7 +92,7 @@ import test_imp_extra_AUTO3 assert mod is test_imp_extra_AUTO3 - def test_load_module_pyc(self): + def test_load_module_pyc_2(self): import os fn = self._pyc_file() try: Modified: pypy/release/1.3.x/pypy/module/itertools/test/test_itertools.py ============================================================================== --- pypy/release/1.3.x/pypy/module/itertools/test/test_itertools.py (original) +++ pypy/release/1.3.x/pypy/module/itertools/test/test_itertools.py Sun Jun 13 00:12:31 2010 @@ -130,7 +130,7 @@ raises(StopIteration, it.next) - def test_takewhile_wrongargs(self): + def test_dropwhile_wrongargs(self): import itertools it = itertools.dropwhile(None, [1]) Modified: pypy/release/1.3.x/pypy/rlib/parsing/test/test_regexparse.py ============================================================================== --- pypy/release/1.3.x/pypy/rlib/parsing/test/test_regexparse.py (original) +++ pypy/release/1.3.x/pypy/rlib/parsing/test/test_regexparse.py Sun Jun 13 00:12:31 2010 @@ -24,7 +24,7 @@ assert r.recognize("kjsadfq3jlflASDF@#$") assert r.recognize("vka afj ASF# A") -def test_quoted(): +def test_quoted_1(): r = make_runner("\\(*") assert r.recognize("(") assert not r.recognize("\\(") @@ -77,7 +77,7 @@ assert not r.recognize("a") assert not r.recognize("c") -def test_quoted(): +def test_quoted_2(): r = make_runner('\\[|\\]|\\|') assert r.recognize("[") assert r.recognize("|") Modified: pypy/release/1.3.x/pypy/rlib/rgc.py ============================================================================== --- pypy/release/1.3.x/pypy/rlib/rgc.py (original) +++ pypy/release/1.3.x/pypy/rlib/rgc.py Sun Jun 13 00:12:31 2010 @@ -201,7 +201,6 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP - from pypy.rpython.lltypesystem import lltype hop.exception_is_here() return hop.genop('gc_heap_stats', [], resulttype=hop.r_result) Modified: pypy/release/1.3.x/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/release/1.3.x/pypy/rlib/test/test_rbigint.py (original) +++ pypy/release/1.3.x/pypy/rlib/test/test_rbigint.py Sun Jun 13 00:12:31 2010 @@ -55,8 +55,6 @@ assert r1.tolong() == r2 def test_touint(self): - import sys - from pypy.rlib.rarithmetic import r_uint result = r_uint(sys.maxint + 42) rl = rbigint.fromint(sys.maxint).add(rbigint.fromint(42)) assert rl.touint() == result Modified: pypy/release/1.3.x/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/release/1.3.x/pypy/rlib/test/test_rmmap.py (original) +++ pypy/release/1.3.x/pypy/rlib/test/test_rmmap.py Sun Jun 13 00:12:31 2010 @@ -3,7 +3,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rlib import rmmap as mmap from pypy.rlib.rmmap import RTypeError, RValueError, alloc, free -import sys class TestMMap: def setup_class(cls): Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/llarena.py Sun Jun 13 00:12:31 2010 @@ -1,5 +1,5 @@ import array, weakref -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import llmemory # An "arena" is a large area of memory which can hold a number of # objects, not necessarily all of the same type or size. It's used by Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/lloperation.py Sun Jun 13 00:12:31 2010 @@ -227,6 +227,8 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), + 'int_between': LLOp(canfold=True), # a <= b < c + 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), # ^^^ more efficient version when 2nd arg is nonneg Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/lltype.py Sun Jun 13 00:12:31 2010 @@ -12,7 +12,6 @@ from pypy.lib.identity_dict import identity_dict from types import NoneType from sys import maxint -import struct import weakref TLS = tlsobject() Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/opimpl.py Sun Jun 13 00:12:31 2010 @@ -197,6 +197,12 @@ assert isinstance(y, int) return intmask(x - y) +def op_int_between(a, b, c): + assert lltype.typeOf(a) is lltype.Signed + assert lltype.typeOf(b) is lltype.Signed + assert lltype.typeOf(c) is lltype.Signed + return a <= b < c + def op_int_and(x, y): if not isinstance(x, int): from pypy.rpython.lltypesystem import llgroup Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/rclass.py Sun Jun 13 00:12:31 2010 @@ -14,7 +14,7 @@ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ Array, Char, Void, \ - FuncType, Bool, Signed, functionptr, FuncType, PyObject + FuncType, Bool, Signed, functionptr, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry @@ -22,6 +22,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel from pypy.lib.identity_dict import identity_dict +from pypy.rpython.lltypesystem.lloperation import llop # # There is one "vtable" per user class, with the following structure: @@ -645,10 +646,12 @@ return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): - return cls.subclassrange_min <= subcls.subclassrange_min <= cls.subclassrange_max + return llop.int_between(Bool, cls.subclassrange_min, + subcls.subclassrange_min, + cls.subclassrange_max) def ll_issubclass_const(subcls, minid, maxid): - return minid <= subcls.subclassrange_min <= maxid + return llop.int_between(Bool, minid, subcls.subclassrange_min, maxid) def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/rffi.py Sun Jun 13 00:12:31 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr -from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof, raw_memcopy +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic @@ -11,7 +11,6 @@ from pypy.rlib import rarithmetic, rgc from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.annlowlevel import llhelper @@ -785,7 +784,6 @@ # the hint is present in structures probed by rffi_platform. size = tp._hints.get('size') if size is None: - from pypy.rpython.lltypesystem import llmemory size = llmemory.sizeof(tp) # a symbolic result in this case return size if isinstance(tp, lltype.Ptr): @@ -814,7 +812,6 @@ if name == fieldname: return fieldoffsets[index] # a symbolic result as a fallback - from pypy.rpython.lltypesystem import llmemory return llmemory.offsetof(STRUCT, fieldname) offsetof._annspecialcase_ = 'specialize:memo' Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sun Jun 13 00:12:31 2010 @@ -15,7 +15,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper -from pypy.tool.udir import udir class TestLL2Ctypes(object): Modified: pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/release/1.3.x/pypy/rpython/lltypesystem/test/test_lltype.py Sun Jun 13 00:12:31 2010 @@ -722,7 +722,6 @@ def test_name_clash(): import re - from pypy.rpython.lltypesystem import lltype fn = lltype.__file__ if fn.lower().endswith('pyc') or fn.lower().endswith('pyo'): fn = fn[:-1] Modified: pypy/release/1.3.x/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/memory/gc/generation.py (original) +++ pypy/release/1.3.x/pypy/rpython/memory/gc/generation.py Sun Jun 13 00:12:31 2010 @@ -720,7 +720,7 @@ return pos elif sys.platform == 'darwin': - from pypy.rpython.lltypesystem import lltype, rffi + from pypy.rpython.lltypesystem import rffi sysctlbyname = rffi.llexternal('sysctlbyname', [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP, Modified: pypy/release/1.3.x/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/release/1.3.x/pypy/rpython/memory/gc/marksweep.py Sun Jun 13 00:12:31 2010 @@ -242,7 +242,6 @@ # 3. walk the list of objects-with-del and for the ones not marked: # call __del__, move the object to the list of object-without-del import time - from pypy.rpython.lltypesystem.lloperation import llop debug_start("gc-collect") start_time = time.time() self.collect_in_progress = True Modified: pypy/release/1.3.x/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/release/1.3.x/pypy/rpython/normalizecalls.py (original) +++ pypy/release/1.3.x/pypy/rpython/normalizecalls.py Sun Jun 13 00:12:31 2010 @@ -292,6 +292,13 @@ else: return cmp(self.orderwitness, other.orderwitness) + # support for implementing int_between: (a<=b> sys.stderr, doc Modified: pypy/release/1.3.x/pypy/tool/sourcetools.py ============================================================================== --- pypy/release/1.3.x/pypy/tool/sourcetools.py (original) +++ pypy/release/1.3.x/pypy/tool/sourcetools.py Sun Jun 13 00:12:31 2010 @@ -129,7 +129,6 @@ for name in names: if name not in kwargs: kwargs[name] = getattr(fromcode, name) - import new return new.code( kwargs['co_argcount'], kwargs['co_nlocals'], Modified: pypy/release/1.3.x/pypy/translator/c/funcgen.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/funcgen.py (original) +++ pypy/release/1.3.x/pypy/translator/c/funcgen.py Sun Jun 13 00:12:31 2010 @@ -318,6 +318,7 @@ def gen_op(self, op): macro = 'OP_%s' % op.opname.upper() + line = None if op.opname.startswith('gc_'): meth = getattr(self.gcpolicy, macro, None) if meth: @@ -326,7 +327,7 @@ meth = getattr(self, macro, None) if meth: line = meth(op) - if meth is None: + if line is None: lst = [self.expr(v) for v in op.args] lst.append(self.expr(op.result)) line = '%s(%s);' % (macro, ', '.join(lst)) @@ -849,5 +850,16 @@ return 'PYPY_DEBUG_CATCH_EXCEPTION("%s", %s, %s);' % ( self.getdebugfunctionname(), gottype, ' || '.join(exprs)) + def OP_INT_BETWEEN(self, op): + if (isinstance(op.args[0], Constant) and + isinstance(op.args[2], Constant) and + op.args[2].value - op.args[0].value == 1): + # (a <= b < a+1) ----> (b == a) + return '%s = (%s == %s); /* was INT_BETWEEN */' % ( + self.expr(op.result), + self.expr(op.args[1]), + self.expr(op.args[0])) + else: + return None # use the default assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/release/1.3.x/pypy/translator/c/src/int.h ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/src/int.h (original) +++ pypy/release/1.3.x/pypy/translator/c/src/int.h Sun Jun 13 00:12:31 2010 @@ -47,6 +47,14 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) +/* Implement INT_BETWEEN by optimizing for the common case where a and c + are constants (the 2nd subtraction below is then constant-folded), or + for the case of a == 0 (both subtractions are then constant-folded). + Note that the following line only works if a <= c in the first place, + which we assume is true. */ +#define OP_INT_BETWEEN(a,b,c,r) r = (((unsigned long)b - (unsigned long)a) \ + < ((unsigned long)c - (unsigned long)a)) + /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) Modified: pypy/release/1.3.x/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/release/1.3.x/pypy/translator/c/test/test_extfunc.py Sun Jun 13 00:12:31 2010 @@ -221,13 +221,6 @@ res = f1() assert res == os.getcwd() -def test_strerror(): - def does_stuff(): - return os.strerror(2) - f1 = compile(does_stuff, []) - res = f1() - assert res == os.strerror(2) - def test_system(): def does_stuff(cmd): return os.system(cmd) Modified: pypy/release/1.3.x/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/test/test_typed.py (original) +++ pypy/release/1.3.x/pypy/translator/c/test/test_typed.py Sun Jun 13 00:12:31 2010 @@ -79,11 +79,6 @@ nested_whiles = self.getcompiled(snippet.nested_whiles, [int, int]) assert nested_whiles(5,3) == '!!!!!' - def test_call_five(self): - call_five = self.getcompiled(snippet.call_five, [int]) - result = call_five() - assert result == [5] - def test_call_unpack_56(self): call_unpack_56 = self.getcompiled(snippet.call_unpack_56, []) result = call_unpack_56() @@ -116,13 +111,6 @@ assert fn(4) == 789 assert fn(5) == 101112 - def test_get_set_del_slice(self): - fn = self.getcompiled(snippet.get_set_del_slice, [list]) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - def test_type_conversion(self): # obfuscated test case specially for typer.insert_link_conversions() def type_conversion(n): From fijal at codespeak.net Sun Jun 13 00:12:58 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 00:12:58 +0200 (CEST) Subject: [pypy-svn] r75353 - in pypy/release/1.3.x/pypy/objspace/std: . test Message-ID: <20100612221258.B34A9282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 00:12:56 2010 New Revision: 75353 Modified: pypy/release/1.3.x/pypy/objspace/std/dictmultiobject.py pypy/release/1.3.x/pypy/objspace/std/dicttype.py pypy/release/1.3.x/pypy/objspace/std/frame.py pypy/release/1.3.x/pypy/objspace/std/settype.py pypy/release/1.3.x/pypy/objspace/std/stringobject.py pypy/release/1.3.x/pypy/objspace/std/test/test_strutil.py pypy/release/1.3.x/pypy/objspace/std/test/test_tupleobject.py pypy/release/1.3.x/pypy/objspace/std/test/test_typeobject.py pypy/release/1.3.x/pypy/objspace/std/test/test_unicodeobject.py pypy/release/1.3.x/pypy/objspace/std/transparent.py Log: Missing part of the previous checkin Modified: pypy/release/1.3.x/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/dictmultiobject.py Sun Jun 13 00:12:56 2010 @@ -467,7 +467,7 @@ # XXX fix this thing -import time, py +import time class DictInfo(object): _dict_infos = [] Modified: pypy/release/1.3.x/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/dicttype.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/dicttype.py Sun Jun 13 00:12:56 2010 @@ -4,7 +4,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.stdtypedef import StdTypeDef, SMM, no_hash_descr from pypy.objspace.std.register_all import register_all -from pypy.interpreter.error import OperationError dict_copy = SMM('copy', 1, doc='D.copy() -> a shallow copy of D') Modified: pypy/release/1.3.x/pypy/objspace/std/frame.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/frame.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/frame.py Sun Jun 13 00:12:56 2010 @@ -130,7 +130,7 @@ w_result = getattr(f, attr)(w_1, w_2) break else: - raise pyopcde.BytecodeCorruption, "bad COMPARE_OP oparg" + raise pyopcode.BytecodeCorruption, "bad COMPARE_OP oparg" f.pushvalue(w_result) @@ -154,6 +154,7 @@ if space.config.objspace.std.optimized_comparison_op: StdObjSpaceFrame.COMPARE_OP = fast_COMPARE_OP if space.config.objspace.std.logspaceoptypes: + assert 0, "logspaceoptypes: a few fixes a missing here" StdObjSpace._space_op_types = [] for name, new in get_logging(): setattr(StdObjSpaceFrame, name, new) Modified: pypy/release/1.3.x/pypy/objspace/std/settype.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/settype.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/settype.py Sun Jun 13 00:12:56 2010 @@ -2,7 +2,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr, SMM -from pypy.interpreter import gateway set_add = SMM('add', 2, doc='Add an element to a set.\n\nThis' Modified: pypy/release/1.3.x/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/stringobject.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/stringobject.py Sun Jun 13 00:12:56 2010 @@ -964,7 +964,6 @@ return mod_format(space, w_format, w_values, do_unicode=False) def buffer__String(space, w_string): - from pypy.interpreter.buffer import StringBuffer return space.wrap(StringBuffer(w_string._value)) # register all methods Modified: pypy/release/1.3.x/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/test/test_strutil.py Sun Jun 13 00:12:56 2010 @@ -2,8 +2,6 @@ from pypy.objspace.std.strutil import * from pypy.interpreter.error import OperationError -import py - class TestStrUtil: Modified: pypy/release/1.3.x/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/test/test_tupleobject.py Sun Jun 13 00:12:56 2010 @@ -289,7 +289,7 @@ assert (t * 1) is not t assert (t * 1) == t - def test_getslice(self): + def test_getslice_2(self): assert (5,2,3)[1:2] == (2,) def test_eq(self): Modified: pypy/release/1.3.x/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/test/test_typeobject.py Sun Jun 13 00:12:56 2010 @@ -1001,12 +1001,12 @@ y.x = 3 assert y.x == 3 - def ga(self, name): - return 'GA' + def ga2(self, name): + return 'GA2' - X.__getattribute__ = ga + X.__getattribute__ = ga2 - assert y.x == 'GA' + assert y.x == 'GA2' class TestNewShortcut: Modified: pypy/release/1.3.x/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/test/test_unicodeobject.py Sun Jun 13 00:12:56 2010 @@ -321,7 +321,7 @@ assert U(u'test') == u'test' assert U(u'test').__class__ is U - def test_call_unicode(self): + def test_call_unicode_2(self): class X(object): def __unicode__(self): return u'x' Modified: pypy/release/1.3.x/pypy/objspace/std/transparent.py ============================================================================== --- pypy/release/1.3.x/pypy/objspace/std/transparent.py (original) +++ pypy/release/1.3.x/pypy/objspace/std/transparent.py Sun Jun 13 00:12:56 2010 @@ -3,7 +3,6 @@ """ from pypy.interpreter import gateway -from pypy.interpreter.function import Function from pypy.interpreter.error import OperationError, operationerrfmt from pypy.objspace.std.proxyobject import * from pypy.objspace.std.typeobject import W_TypeObject From fijal at codespeak.net Sun Jun 13 00:20:06 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 00:20:06 +0200 (CEST) Subject: [pypy-svn] r75354 - pypy/release/1.3.x/pypy/module/imp Message-ID: <20100612222006.4E579282BDD@codespeak.net> Author: fijal Date: Sun Jun 13 00:20:04 2010 New Revision: 75354 Modified: pypy/release/1.3.x/pypy/module/imp/importing.py Log: Only use cpyext if it's loaded. That's an a safety switch saying "I know what I'm doing" when using cpyext Modified: pypy/release/1.3.x/pypy/module/imp/importing.py ============================================================================== --- pypy/release/1.3.x/pypy/module/imp/importing.py (original) +++ pypy/release/1.3.x/pypy/module/imp/importing.py Sun Jun 13 00:20:04 2010 @@ -53,9 +53,18 @@ return PY_COMPILED, ".pyc", "rb" if space.config.objspace.usemodules.cpyext: - pydfile = filepart + so_extension - if os.path.exists(pydfile) and case_ok(pydfile): - return C_EXTENSION, so_extension, "rb" + try: + space.getitem(space.getattr(space.sys, + space.wrap('modules')), + space.wrap('cpyext')) + except OperationError, o: + if not o.match(space, space.w_KeyError): + raise + else: + # cpyext was loaded, try to load cpython extensions + pydfile = filepart + so_extension + if os.path.exists(pydfile) and case_ok(pydfile): + return C_EXTENSION, so_extension, "rb" return SEARCH_ERROR, None, None From fijal at codespeak.net Sun Jun 13 00:44:09 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 00:44:09 +0200 (CEST) Subject: [pypy-svn] r75355 - pypy/build/bot2/pypybuildbot Message-ID: <20100612224409.D0EF6282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 00:44:07 2010 New Revision: 75355 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: We use .tar.bz2 extension these days Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sun Jun 13 00:44:07 2010 @@ -146,7 +146,7 @@ else: kind = 'nojit' nightly = '~/nightly/' - name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + '.bz2' + name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + '.tar.bz2' pypy_c_rel = 'build/pypy/translator/goal/pypy-c.tar.bz2' self.addStep(PyPyUpload(slavesrc=pypy_c_rel, masterdest=WithProperties(nightly), From fijal at codespeak.net Sun Jun 13 02:20:41 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 02:20:41 +0200 (CEST) Subject: [pypy-svn] r75356 - pypy/trunk/pypy/module/zipimport/test Message-ID: <20100613002041.AAAEF282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 02:20:38 2010 New Revision: 75356 Modified: pypy/trunk/pypy/module/zipimport/test/test_undocumented.py pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Log: Bring tests to the state where they pass with -A (I don't care if differences are acceptble or not) Modified: pypy/trunk/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_undocumented.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_undocumented.py Sun Jun 13 02:20:38 2010 @@ -118,7 +118,7 @@ import zipimport, os zip_path = self.temp_zipfile(self.created_paths) try: - prefix = '_pkg' + prefix = '_pkg/' path = os.path.join(zip_path, prefix) zip_importer = zipimport.zipimporter(path) assert isinstance(zip_importer, zipimport.zipimporter) Modified: pypy/trunk/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/test/test_zipimport.py Sun Jun 13 02:20:38 2010 @@ -114,7 +114,7 @@ from zipimport import _zip_directory_cache, zipimporter new_importer = zipimporter(self.zipfile) try: - assert zipimporter(self.zipfile) is new_importer + assert zipimporter(self.zipfile) is not new_importer finally: del _zip_directory_cache[self.zipfile] @@ -128,7 +128,7 @@ assert main_importer is not sub_importer assert main_importer.prefix == "" - assert sub_importer.prefix == "sub\\" + assert sub_importer.prefix == "sub/" def test_good_bad_arguments(self): from zipimport import zipimporter @@ -205,8 +205,7 @@ import zipimport z = zipimport.zipimporter(self.zipfile) sys.modules['uuu'] = lambda x : x + 1 - mod = z.load_module('uuu') - assert mod(3) == 4 + raises(ImportError, z.load_module, 'uuu') def test_package(self): import os, sys @@ -287,7 +286,7 @@ archive = importer.archive realprefix = importer.prefix allbutlast = self.zipfile.split(os.path.sep)[:-1] - prefix = 'directory' + prefix = 'directory/' assert archive == self.zipfile assert realprefix == prefix From fijal at codespeak.net Sun Jun 13 03:51:17 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 03:51:17 +0200 (CEST) Subject: [pypy-svn] r75357 - pypy/build/bot2/pypybuildbot Message-ID: <20100613015117.07FFE282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 03:51:15 2010 New Revision: 75357 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Be robust against os.path.join('x', '/x') returning '/x' Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Sun Jun 13 03:51:15 2010 @@ -22,6 +22,9 @@ branch = 'trunk' masterdest = properties.render(self.masterdest) masterdest = os.path.expanduser(masterdest) + if branch.startswith('/'): + branch = branch[1:] + # workaround for os.path.join masterdest = os.path.join(masterdest, branch) if not os.path.exists(masterdest): os.makedirs(masterdest) From fijal at codespeak.net Sun Jun 13 06:37:13 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 06:37:13 +0200 (CEST) Subject: [pypy-svn] r75358 - pypy/trunk/pypy/module/zipimport Message-ID: <20100613043713.3ABD2282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 06:37:10 2010 New Revision: 75358 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py Log: Change the level of caching. Cache, because we have to, but actually don't reuse the value. Bummer for bug-to-bug compatibility Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Sun Jun 13 06:37:10 2010 @@ -351,7 +351,6 @@ raise operationerrfmt(w_ZipImportError, "Cannot import %s from zipfile, recursion detected or" "already tried and failed", name) - return w_result except KeyError: zip_cache.cache[filename] = None try: From fijal at codespeak.net Sun Jun 13 06:53:19 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 06:53:19 +0200 (CEST) Subject: [pypy-svn] r75359 - pypy/trunk/pypy/module/zipimport Message-ID: <20100613045319.8EBDA282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 06:53:18 2010 New Revision: 75359 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py Log: observe-and-reproduce Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Sun Jun 13 06:53:18 2010 @@ -362,6 +362,8 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] + if prefix and len(name) != len(filename): + prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) zip_cache.set(filename, w_result) From fijal at codespeak.net Sun Jun 13 07:04:48 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:04:48 +0200 (CEST) Subject: [pypy-svn] r75360 - pypy/trunk/pypy/module/zipimport Message-ID: <20100613050448.58A91282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:04:46 2010 New Revision: 75360 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py Log: Don't be too smart. I think this fixes the last difference between -A run (cpython) and our own. I don't really want to know why we introduced features that are incompatible. Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Sun Jun 13 07:04:46 2010 @@ -223,11 +223,6 @@ def load_module(self, space, fullname): w = space.wrap - w_modules = space.sys.get('modules') - try: - return space.getitem(w_modules, w(fullname)) - except OperationError, e: - pass filename = self.mangle(fullname) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: From fijal at codespeak.net Sun Jun 13 07:07:35 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:07:35 +0200 (CEST) Subject: [pypy-svn] r75361 - pypy/trunk/pypy/tool Message-ID: <20100613050735.1398A282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:07:34 2010 New Revision: 75361 Modified: pypy/trunk/pypy/tool/gcc_cache.py Log: Don't cache failures. Repeatadly people had problems with it (including me). Modified: pypy/trunk/pypy/tool/gcc_cache.py ============================================================================== --- pypy/trunk/pypy/tool/gcc_cache.py (original) +++ pypy/trunk/pypy/tool/gcc_cache.py Sun Jun 13 07:07:34 2010 @@ -33,9 +33,9 @@ try: platform.compile(c_files, eci) data = 'True' + path.write(data) except CompilationError, e: data = 'FAIL\n%s\n' % (e,) - path.write(data) if data.startswith('True'): return True else: From fijal at codespeak.net Sun Jun 13 07:10:05 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:10:05 +0200 (CEST) Subject: [pypy-svn] r75362 - in pypy/release/1.3.x: . pypy/module/zipimport pypy/module/zipimport/test Message-ID: <20100613051005.5A4F9282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:10:03 2010 New Revision: 75362 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py pypy/release/1.3.x/pypy/module/zipimport/test/test_undocumented.py pypy/release/1.3.x/pypy/module/zipimport/test/test_zipimport.py Log: Merge 75356 through 75360 (zipimporter changes) Modified: pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py Sun Jun 13 07:10:03 2010 @@ -223,11 +223,6 @@ def load_module(self, space, fullname): w = space.wrap - w_modules = space.sys.get('modules') - try: - return space.getitem(w_modules, w(fullname)) - except OperationError, e: - pass filename = self.mangle(fullname) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: @@ -351,7 +346,6 @@ raise operationerrfmt(w_ZipImportError, "Cannot import %s from zipfile, recursion detected or" "already tried and failed", name) - return w_result except KeyError: zip_cache.cache[filename] = None try: @@ -363,6 +357,8 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] + if prefix and len(name) != len(filename): + prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) zip_cache.set(filename, w_result) Modified: pypy/release/1.3.x/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- pypy/release/1.3.x/pypy/module/zipimport/test/test_undocumented.py (original) +++ pypy/release/1.3.x/pypy/module/zipimport/test/test_undocumented.py Sun Jun 13 07:10:03 2010 @@ -118,7 +118,7 @@ import zipimport, os zip_path = self.temp_zipfile(self.created_paths) try: - prefix = '_pkg' + prefix = '_pkg/' path = os.path.join(zip_path, prefix) zip_importer = zipimport.zipimporter(path) assert isinstance(zip_importer, zipimport.zipimporter) Modified: pypy/release/1.3.x/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/release/1.3.x/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/release/1.3.x/pypy/module/zipimport/test/test_zipimport.py Sun Jun 13 07:10:03 2010 @@ -114,7 +114,7 @@ from zipimport import _zip_directory_cache, zipimporter new_importer = zipimporter(self.zipfile) try: - assert zipimporter(self.zipfile) is new_importer + assert zipimporter(self.zipfile) is not new_importer finally: del _zip_directory_cache[self.zipfile] @@ -128,7 +128,7 @@ assert main_importer is not sub_importer assert main_importer.prefix == "" - assert sub_importer.prefix == "sub\\" + assert sub_importer.prefix == "sub/" def test_good_bad_arguments(self): from zipimport import zipimporter @@ -205,8 +205,7 @@ import zipimport z = zipimport.zipimporter(self.zipfile) sys.modules['uuu'] = lambda x : x + 1 - mod = z.load_module('uuu') - assert mod(3) == 4 + raises(ImportError, z.load_module, 'uuu') def test_package(self): import os, sys @@ -287,7 +286,7 @@ archive = importer.archive realprefix = importer.prefix allbutlast = self.zipfile.split(os.path.sep)[:-1] - prefix = 'directory' + prefix = 'directory/' assert archive == self.zipfile assert realprefix == prefix From fijal at codespeak.net Sun Jun 13 07:13:41 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:13:41 +0200 (CEST) Subject: [pypy-svn] r75363 - pypy/trunk/pypy/tool/release Message-ID: <20100613051341.5DFD0282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:13:38 2010 New Revision: 75363 Modified: pypy/trunk/pypy/tool/release/force-builds.py Log: Add own-* builders here as well Modified: pypy/trunk/pypy/tool/release/force-builds.py ============================================================================== --- pypy/trunk/pypy/tool/release/force-builds.py (original) +++ pypy/trunk/pypy/tool/release/force-builds.py Sun Jun 13 07:13:38 2010 @@ -17,6 +17,9 @@ from twisted.web.error import PageRedirect BUILDERS = [ + 'own-linux-x86-32', + 'own-linux-x86-64', + 'own-macosx-x86-32', 'pypy-c-app-level-linux-x86-32', 'pypy-c-app-level-linux-64', 'pypy-c-stackless-app-level-linux-x86-32', From fijal at codespeak.net Sun Jun 13 07:26:30 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:26:30 +0200 (CEST) Subject: [pypy-svn] r75364 - pypy/trunk/pypy/tool/release Message-ID: <20100613052630.F1E30282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:26:29 2010 New Revision: 75364 Added: pypy/trunk/pypy/tool/release/release.py (contents, props changed) Log: A half-finished script for making releases, IN-PROGRESS Added: pypy/trunk/pypy/tool/release/release.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/release/release.py Sun Jun 13 07:26:29 2010 @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +""" A tool to download correct pypy-c's from nightly build run and package them +into release packages. Note: you must run apropriate buildbots first and +make sure there are no failures. Use force-builds.py from the same directory. + +Usage: release.py release/ +""" + +import sys +import urllib2 +from xml.dom import minidom +import re + +def browse_nightly(branch, + baseurl='http://buildbot.pypy.org/nightly/'): + url = baseurl + branch + '/' + dom = minidom.parseString(urllib2.urlopen(url).read()) + refs = [node.getAttribute('href') for node in dom.getElementsByTagName('a')] + # all refs are of form: pypy-{type}-{revision}-{platform}.tar.bz2 + r = re.compile('pypy-c-([\w\d]+)-(\d+)-([\w\d]+).tar.bz2$') + d = {} + for ref in refs: + kind, rev, platform = r.match(ref).groups() + rev = int(rev) + try: + lastrev, _ = d[(kind, platform)] + except KeyError: + lastrev = -1 + if rev > lastrev: + d[(kind, platform)] = rev, ref + return d + +def main(branch): + to_download = browse_nightly(branch) + xxx # finish me + +if __name__ == '__main__': + if len(sys.argv) != 2: + print __doc__ + sys.exit(1) + main(sys.argv[1]) + From fijal at codespeak.net Sun Jun 13 07:26:50 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 07:26:50 +0200 (CEST) Subject: [pypy-svn] r75365 - pypy/trunk/pypy/tool/release Message-ID: <20100613052650.268C7282BD8@codespeak.net> Author: fijal Date: Sun Jun 13 07:26:48 2010 New Revision: 75365 Added: pypy/trunk/pypy/tool/release/make_release.py - copied, changed from r75364, pypy/trunk/pypy/tool/release/release.py Removed: pypy/trunk/pypy/tool/release/release.py Log: Rename the script Copied: pypy/trunk/pypy/tool/release/make_release.py (from r75364, pypy/trunk/pypy/tool/release/release.py) ============================================================================== --- pypy/trunk/pypy/tool/release/release.py (original) +++ pypy/trunk/pypy/tool/release/make_release.py Sun Jun 13 07:26:48 2010 @@ -4,7 +4,7 @@ into release packages. Note: you must run apropriate buildbots first and make sure there are no failures. Use force-builds.py from the same directory. -Usage: release.py release/ +Usage: make_release.py release/ """ import sys From arigo at codespeak.net Sun Jun 13 11:18:14 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 11:18:14 +0200 (CEST) Subject: [pypy-svn] r75366 - pypy/trunk/pypy/lib/app_test/ctypes_tests Message-ID: <20100613091814.E44EE282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 11:18:12 2010 New Revision: 75366 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py Log: Unsure. I think it's fine to get ArgumentError here. Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py Sun Jun 13 11:18:12 2010 @@ -217,7 +217,7 @@ class X(Structure): _fields_ = [("y", c_int)] - raises(TypeError, f, X()) #cannot convert parameter + raises(ArgumentError, f, X()) #cannot convert parameter ################################################################ def test_shorts(self): From arigo at codespeak.net Sun Jun 13 11:36:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 11:36:50 +0200 (CEST) Subject: [pypy-svn] r75367 - in pypy/branch/multijit-4/pypy/module/__builtin__: . test Message-ID: <20100613093650.85A30282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 11:36:48 2010 New Revision: 75367 Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py Log: Merge r75331 and r75332 from trunk. Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Sun Jun 13 11:36:48 2010 @@ -187,13 +187,15 @@ cont = False args_w = [space.w_None] * num_iterators for i in range(num_iterators): - try: - args_w[i] = space.next(iterators_w[i]) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - else: - cont = True + if iterators_w[i] is not None: + try: + args_w[i] = space.next(iterators_w[i]) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + iterators_w[i] = None + else: + cont = True if cont: w_args = space.newtuple(args_w) if none_func: Modified: pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py Sun Jun 13 11:36:48 2010 @@ -58,6 +58,25 @@ b = [] assert map(lambda x, y: x, a, b) == a + def test_map_iterables(self): + class A(object): + def __init__(self, n): + self.n = n + def __iter__(self): + return B(self.n) + class B(object): + def __init__(self, n): + self.n = n + def next(self): + self.n -= 1 + if self.n == 0: raise StopIteration + return self.n + result = map(None, A(3), A(8)) + # this also checks that B.next() is not called any more after it + # raised StopIteration once + assert result == [(2, 7), (1, 6), (None, 5), (None, 4), + (None, 3), (None, 2), (None, 1)] + class AppTestZip: def test_one_list(self): assert zip([1,2,3]) == [(1,), (2,), (3,)] From arigo at codespeak.net Sun Jun 13 11:43:37 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 11:43:37 +0200 (CEST) Subject: [pypy-svn] r75368 - pypy/branch/multijit-4/pypy/module/__builtin__ Message-ID: <20100613094337.E1A02282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 11:43:36 2010 New Revision: 75368 Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Log: Write a special case for the most common use case for map(). Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Sun Jun 13 11:43:36 2010 @@ -158,6 +158,21 @@ return min_max(space, __args__, "min") min.unwrap_spec = [ObjSpace, Arguments] +def map_single_collection(space, w_func, w_collection): + """Special case for 'map(func, coll)', where 'func' is not None and there + is only one 'coll' argument.""" + w_iter = space.iter(w_collection) + result_w = [] + while True: + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + result_w.append(space.call_function(w_func, w_item)) + return space.newlist(result_w) + def map(space, w_func, collections_w): """does 3 separate things, hence this enormous docstring. 1. if function is None, return a list of tuples, each with one @@ -176,10 +191,13 @@ if not collections_w: msg = "map() requires at least two arguments" raise OperationError(space.w_TypeError, space.wrap(msg)) - num_collections = len(collections_w) none_func = space.is_w(w_func, space.w_None) - if none_func and num_collections == 1: - return space.call_function(space.w_list, collections_w[0]) + if len(collections_w) == 1: + w_collection = collections_w[0] + if none_func: + return space.call_function(space.w_list, w_collection) + else: + return map_single_collection(space, w_func, w_collection) result_w = [] iterators_w = [space.iter(w_seq) for w_seq in collections_w] num_iterators = len(iterators_w) @@ -199,10 +217,10 @@ if cont: w_args = space.newtuple(args_w) if none_func: - result_w.append(w_args) + w_res = w_args else: w_res = space.call(w_func, w_args) - result_w.append(w_res) + result_w.append(w_res) else: return space.newlist(result_w) map.unwrap_spec = [ObjSpace, W_Root, "args_w"] From arigo at codespeak.net Sun Jun 13 12:37:51 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 12:37:51 +0200 (CEST) Subject: [pypy-svn] r75369 - in pypy/branch/multijit-4/pypy/module/__builtin__: . test Message-ID: <20100613103751.AD120282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 12:37:50 2010 New Revision: 75369 Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py Log: Trying to hack a JitDriver there... Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Sun Jun 13 12:37:50 2010 @@ -158,21 +158,6 @@ return min_max(space, __args__, "min") min.unwrap_spec = [ObjSpace, Arguments] -def map_single_collection(space, w_func, w_collection): - """Special case for 'map(func, coll)', where 'func' is not None and there - is only one 'coll' argument.""" - w_iter = space.iter(w_collection) - result_w = [] - while True: - try: - w_item = space.next(w_iter) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - break - result_w.append(space.call_function(w_func, w_item)) - return space.newlist(result_w) - def map(space, w_func, collections_w): """does 3 separate things, hence this enormous docstring. 1. if function is None, return a list of tuples, each with one @@ -195,9 +180,63 @@ if len(collections_w) == 1: w_collection = collections_w[0] if none_func: - return space.call_function(space.w_list, w_collection) + result_w = space.unpackiterable(w_collection) else: - return map_single_collection(space, w_func, w_collection) + result_w = map_single_collection(space, w_func, w_collection) + else: + result_w = map_multiple_collections(space, w_func, collections_w, + none_func) + return space.newlist(result_w) +map.unwrap_spec = [ObjSpace, W_Root, "args_w"] + +def map_single_collection(space, w_func, w_collection): + """Special case for 'map(func, coll)', where 'func' is not None and there + is only one 'coll' argument.""" + w_iter = space.iter(w_collection) + # xxx special hacks for speed + from pypy.interpreter import function, pycode + if isinstance(w_func, function.Function): + # xxx compatibility issue: what if func_code is modified in the + # middle of running map()?? That's far too obscure for me to care... + code = w_func.getcode() + fast_natural_arity = code.fast_natural_arity + if fast_natural_arity == (1|pycode.PyCode.FLATPYCALL): + assert isinstance(code, pycode.PyCode) + return map_single_user_function(code, w_func, w_iter) + # /xxx end of special hacks + result_w = [] + while True: + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + result_w.append(space.call_function(w_func, w_item)) + return result_w + +from pypy.rlib.jit import JitDriver +mapjitdriver = JitDriver(greens = ['code'], reds = ['w_func', 'w_iter']) +def map_single_user_function(code, w_func, w_iter): + result_w = [] + while True: + mapjitdriver.can_enter_jit(code=code, w_func=w_func, w_iter=w_iter) + mapjitdriver.jit_merge_point(code=code, w_func=w_func, w_iter=w_iter) + space = w_func.space + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + new_frame = space.createframe(code, w_func.w_func_globals, + w_func.closure) + new_frame.fastlocals_w[0] = w_item + w_res = new_frame.run() + result_w.append(w_res) + return result_w + +def map_multiple_collections(space, w_func, collections_w, none_func): result_w = [] iterators_w = [space.iter(w_seq) for w_seq in collections_w] num_iterators = len(iterators_w) @@ -214,16 +253,15 @@ iterators_w[i] = None else: cont = True - if cont: - w_args = space.newtuple(args_w) - if none_func: - w_res = w_args - else: - w_res = space.call(w_func, w_args) - result_w.append(w_res) + if not cont: + break + w_args = space.newtuple(args_w) + if none_func: + w_res = w_args else: - return space.newlist(result_w) -map.unwrap_spec = [ObjSpace, W_Root, "args_w"] + w_res = space.call(w_func, w_args) + result_w.append(w_res) + return result_w def sum(space, w_sequence, w_start=None): if space.is_w(w_start, space.w_None): Modified: pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/test/test_functional.py Sun Jun 13 12:37:50 2010 @@ -6,6 +6,9 @@ def test_trivial_map_one_seq(self): assert map(lambda x: x+2, [1, 2, 3, 4]) == [3, 4, 5, 6] + def test_trivial_map_one_seq_2(self): + assert map(str, [1, 2, 3, 4]) == ['1', '2', '3', '4'] + def test_trivial_map_two_seq(self): assert map(lambda x,y: x+y, [1, 2, 3, 4],[1, 2, 3, 4]) == ( From arigo at codespeak.net Sun Jun 13 13:14:55 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 13:14:55 +0200 (CEST) Subject: [pypy-svn] r75370 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100613111455.7BA5F282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 13:14:54 2010 New Revision: 75370 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py Log: A translation test for two JITs. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py Sun Jun 13 13:14:54 2010 @@ -20,6 +20,7 @@ # - profiler # - full optimizer # - jitdriver hooks + # - two JITs class Frame(object): _virtualizable2_ = ['i'] @@ -61,14 +62,27 @@ frame.i -= 2 frame.i -= 1 return total * 10 - res = ll_meta_interp(f, [40], CPUClass=self.CPUClass, + # + myjitdriver2 = JitDriver(greens = [], reds = ['m', 'x']) + def f2(m, x): + while m > 0: + myjitdriver2.can_enter_jit(m=m, x=x) + myjitdriver2.jit_merge_point(m=m, x=x) + m -= 1 + x += 3 + return x + # + def main(i, j): + return f(i) - f2(i, j) + res = ll_meta_interp(main, [40, 5], CPUClass=self.CPUClass, type_system=self.type_system) - assert res == f(40) - res = rpython_ll_meta_interp(f, [40], loops=2, CPUClass=self.CPUClass, + assert res == main(40, 5) + res = rpython_ll_meta_interp(main, [40, 5], loops=2, + CPUClass=self.CPUClass, type_system=self.type_system, optimizer=OPTIMIZER_FULL, ProfilerClass=Profiler) - assert res == f(40) + assert res == main(40, 5) def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) From arigo at codespeak.net Sun Jun 13 14:08:52 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 14:08:52 +0200 (CEST) Subject: [pypy-svn] r75371 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100613120852.D6273282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 14:08:51 2010 New Revision: 75371 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py Log: If the JitDrivers take incompatible greens, we get an annotation crash. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_ztranslation.py Sun Jun 13 14:08:51 2010 @@ -63,17 +63,18 @@ frame.i -= 1 return total * 10 # - myjitdriver2 = JitDriver(greens = [], reds = ['m', 'x']) - def f2(m, x): + myjitdriver2 = JitDriver(greens = ['g'], reds = ['m', 'x'], + can_inline = lambda *args: False) + def f2(g, m, x): while m > 0: - myjitdriver2.can_enter_jit(m=m, x=x) - myjitdriver2.jit_merge_point(m=m, x=x) + myjitdriver2.can_enter_jit(g=g, m=m, x=x) + myjitdriver2.jit_merge_point(g=g, m=m, x=x) m -= 1 x += 3 return x # def main(i, j): - return f(i) - f2(i, j) + return f(i) - f2(i+j, i, j) res = ll_meta_interp(main, [40, 5], CPUClass=self.CPUClass, type_system=self.type_system) assert res == main(40, 5) From arigo at codespeak.net Sun Jun 13 14:12:41 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 14:12:41 +0200 (CEST) Subject: [pypy-svn] r75372 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100613121241.5D2B6282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 14:12:40 2010 New Revision: 75372 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Log: Fix for r75371. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmstate.py Sun Jun 13 14:12:40 2010 @@ -470,6 +470,7 @@ # can_inline_ptr = self.jitdriver_sd._can_inline_ptr unwrap_greenkey = self.make_unwrap_greenkey() + jit_getter = self.make_jitcell_getter() if can_inline_ptr is None: def can_inline_callable(*greenargs): # XXX shouldn't it be False by default? @@ -481,7 +482,7 @@ fn = support.maybe_on_top_of_llinterp(rtyper, can_inline_ptr) return fn(*greenargs) def can_inline(*greenargs): - cell = self.jit_getter(*greenargs) + cell = jit_getter(*greenargs) if cell.dont_trace_here: return False return can_inline_callable(*greenargs) @@ -490,11 +491,10 @@ greenargs = unwrap_greenkey(greenkey) return can_inline(*greenargs) self.can_inline_callable = can_inline_greenkey - - get_jitcell = self.make_jitcell_getter() + def get_assembler_token(greenkey): greenargs = unwrap_greenkey(greenkey) - cell = get_jitcell(*greenargs) + cell = jit_getter(*greenargs) if cell.counter >= 0: return None return cell.entry_loop_token From arigo at codespeak.net Sun Jun 13 14:13:42 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 14:13:42 +0200 (CEST) Subject: [pypy-svn] r75373 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100613121342.2B125282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 14:13:40 2010 New Revision: 75373 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Log: Don't use portal_runner_ptr, but only portal_runner_adr, because the first one is not type-safe. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/blackhole.py Sun Jun 13 14:13:40 2010 @@ -792,8 +792,7 @@ def get_portal_runner(self, jdindex): jitdriver_sd = self.builder.metainterp_sd.jitdrivers_sd[jdindex] - fnptr = llmemory.cast_ptr_to_adr(jitdriver_sd.portal_runner_ptr) - fnptr = heaptracker.adr2int(fnptr) + fnptr = heaptracker.adr2int(jitdriver_sd.portal_runner_adr) calldescr = jitdriver_sd.mainjitcode.calldescr return fnptr, calldescr Modified: pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py Sun Jun 13 14:13:40 2010 @@ -7,6 +7,7 @@ # self.jitdriver ... pypy.jit.metainterp.warmspot # self.portal_graph ... pypy.jit.metainterp.warmspot # self.portal_runner_ptr ... pypy.jit.metainterp.warmspot + # self.portal_runner_adr ... pypy.jit.metainterp.warmspot # self.num_green_args ... pypy.jit.metainterp.warmspot # self.result_type ... pypy.jit.metainterp.warmspot # self.virtualizable_info... pypy.jit.metainterp.warmspot Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sun Jun 13 14:13:40 2010 @@ -668,7 +668,7 @@ # that assembler that we call is still correct self.verify_green_args(targetjitdriver_sd, greenboxes) # - k = llmemory.cast_ptr_to_adr(targetjitdriver_sd.portal_runner_ptr) + k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) return self.do_residual_call(funcbox, portal_code.calldescr, allboxes, assembler_call_token=token, Modified: pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/warmspot.py Sun Jun 13 14:13:40 2010 @@ -614,6 +614,7 @@ jd._ll_portal_runner = ll_portal_runner # for debugging jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE, ll_portal_runner) + jd.portal_runner_adr = llmemory.cast_ptr_to_adr(jd.portal_runner_ptr) self.cpu.portal_calldescr = self.cpu.calldescrof( jd._PTR_PORTAL_FUNCTYPE.TO, jd._PTR_PORTAL_FUNCTYPE.TO.ARGS, From arigo at codespeak.net Sun Jun 13 14:14:03 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 14:14:03 +0200 (CEST) Subject: [pypy-svn] r75374 - pypy/branch/multijit-4/pypy/module/__builtin__ Message-ID: <20100613121403.C6A9F282BDC@codespeak.net> Author: arigo Date: Sun Jun 13 14:14:02 2010 New Revision: 75374 Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Log: Fixes to the mapjitdriver. Modified: pypy/branch/multijit-4/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/multijit-4/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/multijit-4/pypy/module/__builtin__/functional.py Sun Jun 13 14:14:02 2010 @@ -204,6 +204,9 @@ assert isinstance(code, pycode.PyCode) return map_single_user_function(code, w_func, w_iter) # /xxx end of special hacks + return map_single_other_callable(space, w_func, w_iter) + +def map_single_other_callable(space, w_func, w_iter): result_w = [] while True: try: @@ -214,14 +217,19 @@ break result_w.append(space.call_function(w_func, w_item)) return result_w +map_single_other_callable._dont_inline_ = True from pypy.rlib.jit import JitDriver -mapjitdriver = JitDriver(greens = ['code'], reds = ['w_func', 'w_iter']) +mapjitdriver = JitDriver(greens = ['code'], + reds = ['w_func', 'w_iter', 'result_w'], + can_inline = lambda *args: False) def map_single_user_function(code, w_func, w_iter): result_w = [] while True: - mapjitdriver.can_enter_jit(code=code, w_func=w_func, w_iter=w_iter) - mapjitdriver.jit_merge_point(code=code, w_func=w_func, w_iter=w_iter) + mapjitdriver.can_enter_jit(code=code, w_func=w_func, + w_iter=w_iter, result_w=result_w) + mapjitdriver.jit_merge_point(code=code, w_func=w_func, + w_iter=w_iter, result_w=result_w) space = w_func.space try: w_item = space.next(w_iter) From arigo at codespeak.net Sun Jun 13 16:11:13 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 16:11:13 +0200 (CEST) Subject: [pypy-svn] r75375 - in pypy/trunk/pypy/tool: . test Message-ID: <20100613141113.9E62C282BD4@codespeak.net> Author: arigo Date: Sun Jun 13 16:11:12 2010 New Revision: 75375 Modified: pypy/trunk/pypy/tool/runsubprocess.py pypy/trunk/pypy/tool/test/test_runsubprocess.py Log: Test and fix for the case (caused I believe by forking) of a subprocess that dies. In that case, re-create one and too bad if this gives you an ENOMEM; this is supposed to be a rare case seen during development. Modified: pypy/trunk/pypy/tool/runsubprocess.py ============================================================================== --- pypy/trunk/pypy/tool/runsubprocess.py (original) +++ pypy/trunk/pypy/tool/runsubprocess.py Sun Jun 13 16:11:12 2010 @@ -5,7 +5,6 @@ import sys import os -import warnings from subprocess import PIPE, Popen def run_subprocess(executable, args, env=None, cwd=None): @@ -46,16 +45,21 @@ # do this at import-time, when the process is still tiny _source = os.path.dirname(os.path.abspath(__file__)) _source = os.path.join(_source, 'runsubprocess.py') # and not e.g. '.pyc' - # Let's not hear about os.popen2's deprecation. - warnings.filterwarnings("ignore", ".*popen2.*", DeprecationWarning, - "pypy.tool.runsubprocess") - _child_stdin, _child_stdout = os.popen2( - "'%s' '%s'" % (sys.executable, _source)) + + def spawn_subprocess(): + global _child + _child = Popen([sys.executable, _source], bufsize=0, + stdin=PIPE, stdout=PIPE, close_fds=True) + spawn_subprocess() def _run(*args): - _child_stdin.write('%r\n' % (args,)) - _child_stdin.flush() - results = _child_stdout.readline() + try: + _child.stdin.write('%r\n' % (args,)) + except (OSError, IOError): + # lost the child. Try again... + spawn_subprocess() + _child.stdin.write('%r\n' % (args,)) + results = _child.stdout.readline() assert results.startswith('(') results = eval(results) if results[0] is None: Modified: pypy/trunk/pypy/tool/test/test_runsubprocess.py ============================================================================== --- pypy/trunk/pypy/tool/test/test_runsubprocess.py (original) +++ pypy/trunk/pypy/tool/test/test_runsubprocess.py Sun Jun 13 16:11:12 2010 @@ -30,3 +30,12 @@ assert returncode == 1 assert stdout == '' assert 'no/such/filename' in stderr + +def test_recover_lost_process(): + if not hasattr(os, 'fork'): + py.test.skip("there is no os.fork()") + from pypy.tool import runsubprocess + import signal + os.kill(runsubprocess._child.pid, signal.SIGTERM) + runsubprocess._child.wait() + test_echo() From arigo at codespeak.net Sun Jun 13 16:12:08 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 16:12:08 +0200 (CEST) Subject: [pypy-svn] r75376 - in pypy/branch/multijit-4/pypy/tool: . test Message-ID: <20100613141208.C5184282BD4@codespeak.net> Author: arigo Date: Sun Jun 13 16:12:07 2010 New Revision: 75376 Modified: pypy/branch/multijit-4/pypy/tool/runsubprocess.py pypy/branch/multijit-4/pypy/tool/test/test_runsubprocess.py Log: Merge r75375 from trunk. Modified: pypy/branch/multijit-4/pypy/tool/runsubprocess.py ============================================================================== --- pypy/branch/multijit-4/pypy/tool/runsubprocess.py (original) +++ pypy/branch/multijit-4/pypy/tool/runsubprocess.py Sun Jun 13 16:12:07 2010 @@ -5,7 +5,6 @@ import sys import os -import warnings from subprocess import PIPE, Popen def run_subprocess(executable, args, env=None, cwd=None): @@ -46,16 +45,21 @@ # do this at import-time, when the process is still tiny _source = os.path.dirname(os.path.abspath(__file__)) _source = os.path.join(_source, 'runsubprocess.py') # and not e.g. '.pyc' - # Let's not hear about os.popen2's deprecation. - warnings.filterwarnings("ignore", ".*popen2.*", DeprecationWarning, - "pypy.tool.runsubprocess") - _child_stdin, _child_stdout = os.popen2( - "'%s' '%s'" % (sys.executable, _source)) + + def spawn_subprocess(): + global _child + _child = Popen([sys.executable, _source], bufsize=0, + stdin=PIPE, stdout=PIPE, close_fds=True) + spawn_subprocess() def _run(*args): - _child_stdin.write('%r\n' % (args,)) - _child_stdin.flush() - results = _child_stdout.readline() + try: + _child.stdin.write('%r\n' % (args,)) + except (OSError, IOError): + # lost the child. Try again... + spawn_subprocess() + _child.stdin.write('%r\n' % (args,)) + results = _child.stdout.readline() assert results.startswith('(') results = eval(results) if results[0] is None: Modified: pypy/branch/multijit-4/pypy/tool/test/test_runsubprocess.py ============================================================================== --- pypy/branch/multijit-4/pypy/tool/test/test_runsubprocess.py (original) +++ pypy/branch/multijit-4/pypy/tool/test/test_runsubprocess.py Sun Jun 13 16:12:07 2010 @@ -30,3 +30,12 @@ assert returncode == 1 assert stdout == '' assert 'no/such/filename' in stderr + +def test_recover_lost_process(): + if not hasattr(os, 'fork'): + py.test.skip("there is no os.fork()") + from pypy.tool import runsubprocess + import signal + os.kill(runsubprocess._child.pid, signal.SIGTERM) + runsubprocess._child.wait() + test_echo() From arigo at codespeak.net Sun Jun 13 17:13:56 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 17:13:56 +0200 (CEST) Subject: [pypy-svn] r75377 - pypy/trunk/pypy/tool Message-ID: <20100613151356.83A4C282BD4@codespeak.net> Author: arigo Date: Sun Jun 13 17:13:55 2010 New Revision: 75377 Modified: pypy/trunk/pypy/tool/runsubprocess.py Log: Clean-up explicitly. Required on top of CPython to avoid suspitious errors at process exit. Modified: pypy/trunk/pypy/tool/runsubprocess.py ============================================================================== --- pypy/trunk/pypy/tool/runsubprocess.py (original) +++ pypy/trunk/pypy/tool/runsubprocess.py Sun Jun 13 17:13:55 2010 @@ -27,7 +27,9 @@ if __name__ == '__main__': + import gc while True: + gc.collect() operation = sys.stdin.readline() if not operation: sys.exit() @@ -52,6 +54,11 @@ stdin=PIPE, stdout=PIPE, close_fds=True) spawn_subprocess() + def cleanup_subprocess(): + global _child + _child = None + import atexit; atexit.register(cleanup_subprocess) + def _run(*args): try: _child.stdin.write('%r\n' % (args,)) From arigo at codespeak.net Sun Jun 13 17:23:55 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 17:23:55 +0200 (CEST) Subject: [pypy-svn] r75378 - pypy/branch/multijit-4/pypy/jit/metainterp Message-ID: <20100613152355.4ED66282BD4@codespeak.net> Author: arigo Date: Sun Jun 13 17:23:53 2010 New Revision: 75378 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Log: Fix. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/pyjitpl.py Sun Jun 13 17:23:53 2010 @@ -506,6 +506,8 @@ def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable # that is stored in metainterp.virtualizable_boxes[-1] + if self.metainterp.jitdriver_sd.virtualizable_info is None: + return True # can occur in case of multiple JITs standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False From fijal at codespeak.net Sun Jun 13 18:59:06 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 18:59:06 +0200 (CEST) Subject: [pypy-svn] r75379 - pypy/trunk/pypy/rlib Message-ID: <20100613165906.EE5D6282BD4@codespeak.net> Author: fijal Date: Sun Jun 13 18:59:05 2010 New Revision: 75379 Modified: pypy/trunk/pypy/rlib/jit.py Log: Add a bit of docstrings Modified: pypy/trunk/pypy/rlib/jit.py ============================================================================== --- pypy/trunk/pypy/rlib/jit.py (original) +++ pypy/trunk/pypy/rlib/jit.py Sun Jun 13 18:59:05 2010 @@ -6,17 +6,38 @@ from pypy.rlib.unroll import unrolling_iterable def purefunction(func): + """ Decorate a function as pure. Pure means precisely that: + + (1) the result of the call should not change if the arguments are + the same (same numbers or same pointers) + (2) it's fine to remove the call completely if we can guess the result + according to rule 1 + + Most importantly it doesn't mean that pure function has no observable + side effect, but those side effects can be ommited (ie caching). + """ func._pure_function_ = True return func def hint(x, **kwds): + """ Hint for the JIT + + possible arguments are: + XXX + """ return x def dont_look_inside(func): + """ Make sure the JIT does not trace inside decorated function + (it becomes a call instead) + """ func._jit_look_inside_ = False return func def unroll_safe(func): + """ JIT can safely unroll loops in this function and this will + not lead to code explosion + """ func._jit_unroll_safe_ = True return func @@ -26,6 +47,9 @@ return func def purefunction_promote(promote_args='all'): + """ A decorator that promotes all arguments and then calls the supplied + function + """ def decorator(func): import inspect purefunction(func) From fijal at codespeak.net Sun Jun 13 19:04:04 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 19:04:04 +0200 (CEST) Subject: [pypy-svn] r75380 - pypy/trunk/pypy/rlib Message-ID: <20100613170404.4D1B5282BD4@codespeak.net> Author: fijal Date: Sun Jun 13 19:04:02 2010 New Revision: 75380 Modified: pypy/trunk/pypy/rlib/jit.py Log: Another docstring Modified: pypy/trunk/pypy/rlib/jit.py ============================================================================== --- pypy/trunk/pypy/rlib/jit.py (original) +++ pypy/trunk/pypy/rlib/jit.py Sun Jun 13 19:04:02 2010 @@ -42,6 +42,11 @@ return func def loop_invariant(func): + """ Describes a function with no argument that returns an object that + is always the same in a loop. + + Use it only if you know what you're doing. + """ dont_look_inside(func) func._jit_loop_invariant_ = True return func From fijal at codespeak.net Sun Jun 13 20:16:51 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 20:16:51 +0200 (CEST) Subject: [pypy-svn] r75381 - in pypy/trunk/pypy/tool/release: . test Message-ID: <20100613181651.11DF0282BD4@codespeak.net> Author: fijal Date: Sun Jun 13 20:16:48 2010 New Revision: 75381 Added: pypy/trunk/pypy/tool/release/test/nightly.xml pypy/trunk/pypy/tool/release/test/test_make_release.py Modified: pypy/trunk/pypy/tool/release/make_release.py Log: Write a test Modified: pypy/trunk/pypy/tool/release/make_release.py ============================================================================== --- pypy/trunk/pypy/tool/release/make_release.py (original) +++ pypy/trunk/pypy/tool/release/make_release.py Sun Jun 13 20:16:48 2010 @@ -13,9 +13,14 @@ import re def browse_nightly(branch, - baseurl='http://buildbot.pypy.org/nightly/'): - url = baseurl + branch + '/' - dom = minidom.parseString(urllib2.urlopen(url).read()) + baseurl='http://buildbot.pypy.org/nightly/', + override_xml=None): + if override_xml is None: + url = baseurl + branch + '/' + xml = urllib2.urlopen(url).read() + else: + xml = override_xml + dom = minidom.parseString(xml) refs = [node.getAttribute('href') for node in dom.getElementsByTagName('a')] # all refs are of form: pypy-{type}-{revision}-{platform}.tar.bz2 r = re.compile('pypy-c-([\w\d]+)-(\d+)-([\w\d]+).tar.bz2$') Added: pypy/trunk/pypy/tool/release/test/nightly.xml ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/release/test/nightly.xml Sun Jun 13 20:16:48 2010 @@ -0,0 +1,94 @@ + + + + Directory listing for /nightly/release/1.3.x/ + + + +

Directory listing for /nightly/release/1.3.x/ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FilenameContent typeContent encoding
pypy-c-jit-75357-linux.tar.bz2[application/x-tar][bzip2]
pypy-c-jit-75357-win32.tar.bz2[application/x-tar][bzip2]
pypy-c-jit-75362-linux.tar.bz2[application/x-tar][bzip2]
pypy-c-jit-75362-win32.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75357-linux.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75357-linux64.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75357-win32.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75362-linux.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75362-linux64.tar.bz2[application/x-tar][bzip2]
pypy-c-nojit-75362-win32.tar.bz2[application/x-tar][bzip2]
pypy-c-stackless-75357-linux.tar.bz2[application/x-tar][bzip2]
pypy-c-stackless-75362-linux.tar.bz2[application/x-tar][bzip2]
+ + Added: pypy/trunk/pypy/tool/release/test/test_make_release.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/tool/release/test/test_make_release.py Sun Jun 13 20:16:48 2010 @@ -0,0 +1,11 @@ + +import py +from pypy.tool.release.make_release import browse_nightly + +XML = py.path.local(__file__).join('..', 'nightly.xml').read() + +def test_browse_nightly(): + res = browse_nightly('branch', override_xml=XML) + assert res[('jit', 'linux')] == (75362, 'pypy-c-jit-75362-linux.tar.bz2') + assert len(res) == 6 + assert res[('nojit', 'linux64')] == (75362, u'pypy-c-nojit-75362-linux64.tar.bz2') From fijal at codespeak.net Sun Jun 13 20:41:09 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jun 2010 20:41:09 +0200 (CEST) Subject: [pypy-svn] r75382 - pypy/trunk/pypy/tool/release Message-ID: <20100613184109.B040636C53A@codespeak.net> Author: fijal Date: Sun Jun 13 20:41:07 2010 New Revision: 75382 Modified: pypy/trunk/pypy/tool/release/pack.py Log: Correct the dll name. Modified: pypy/trunk/pypy/tool/release/pack.py ============================================================================== --- pypy/trunk/pypy/tool/release/pack.py (original) +++ pypy/trunk/pypy/tool/release/pack.py Sun Jun 13 20:41:07 2010 @@ -10,7 +10,7 @@ def filenames_from_platform(platform): if platform == 'win32': files = [goal_dir / 'pypy-c.exe'] - dll = goal_dir.join('pypy-c.dll') + dll = goal_dir.join('libpypy-c.exe.dll') if dll.check(): files.append(dll) else: From arigo at codespeak.net Sun Jun 13 21:23:41 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jun 2010 21:23:41 +0200 (CEST) Subject: [pypy-svn] r75383 - pypy/trunk/pypy/rlib Message-ID: <20100613192341.56F3F282BD4@codespeak.net> Author: arigo Date: Sun Jun 13 21:23:36 2010 New Revision: 75383 Modified: pypy/trunk/pypy/rlib/jit.py Log: Add a comment. Modified: pypy/trunk/pypy/rlib/jit.py ============================================================================== --- pypy/trunk/pypy/rlib/jit.py (original) +++ pypy/trunk/pypy/rlib/jit.py Sun Jun 13 21:23:36 2010 @@ -15,6 +15,7 @@ Most importantly it doesn't mean that pure function has no observable side effect, but those side effects can be ommited (ie caching). + For now, such a function should never raise an exception. """ func._pure_function_ = True return func From fijal at codespeak.net Mon Jun 14 07:18:03 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jun 2010 07:18:03 +0200 (CEST) Subject: [pypy-svn] r75384 - pypy/trunk/pypy/module/zipimport Message-ID: <20100614051803.D9A32282BEC@codespeak.net> Author: fijal Date: Mon Jun 14 07:18:01 2010 New Revision: 75384 Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py Log: Eh, another try to fix it. Also strike redundant if Modified: pypy/trunk/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/trunk/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/trunk/pypy/module/zipimport/interp_zipimport.py Mon Jun 14 07:18:01 2010 @@ -357,7 +357,7 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] - if prefix and len(name) != len(filename): + if prefix and not prefix.endswith(ZIPSEP): prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) From fijal at codespeak.net Mon Jun 14 08:10:32 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jun 2010 08:10:32 +0200 (CEST) Subject: [pypy-svn] r75385 - in pypy/release/1.3.x: . pypy/module/zipimport Message-ID: <20100614061032.5EEE4282BEC@codespeak.net> Author: fijal Date: Mon Jun 14 08:10:30 2010 New Revision: 75385 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py Log: Merge 75384 from trunk. Modified: pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/release/1.3.x/pypy/module/zipimport/interp_zipimport.py Mon Jun 14 08:10:30 2010 @@ -357,7 +357,7 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] - if prefix and len(name) != len(filename): + if prefix and not prefix.endswith(ZIPSEP): prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) From arigo at codespeak.net Mon Jun 14 10:37:37 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jun 2010 10:37:37 +0200 (CEST) Subject: [pypy-svn] r75386 - pypy/branch/multijit-4/pypy/rlib/rsre Message-ID: <20100614083737.9A081282BDC@codespeak.net> Author: arigo Date: Mon Jun 14 10:37:35 2010 New Revision: 75386 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py Log: No-op. Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py Mon Jun 14 10:37:35 2010 @@ -41,6 +41,7 @@ SRE_INFO_LITERAL = 2 SRE_FLAG_LOCALE = 4 # honour system locale SRE_FLAG_UNICODE = 32 # use unicode locale +OPCODE_SUCCESS = 1 OPCODE_INFO = 17 OPCODE_LITERAL = 19 MAXREPEAT = 65535 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py Mon Jun 14 10:37:35 2010 @@ -12,6 +12,7 @@ from pypy.rlib.rsre import rsre_char from pypy.rlib.rsre.rsre_char import SRE_INFO_PREFIX, SRE_INFO_LITERAL from pypy.rlib.rsre.rsre_char import OPCODE_INFO, MAXREPEAT +from pypy.rlib.rsre.rsre_char import OPCODE_SUCCESS, OPCODE_LITERAL from pypy.rlib.unroll import unrolling_iterable #### Core classes @@ -456,7 +457,7 @@ if count < mincount: ctx.has_matched = ctx.NOT_MATCHED return True - if ctx.peek_code(ctx.peek_code(1) + 1) == 1: # 1 == OPCODES["success"] + if ctx.peek_code(ctx.peek_code(1) + 1) == OPCODE_SUCCESS: # tail is empty. we're finished ctx.state.string_position = ctx.string_position ctx.has_matched = ctx.MATCHED @@ -480,7 +481,7 @@ # ok = True nextidx = ctx.peek_code(1) - if ctx.peek_code(nextidx + 1) == 19: # 19 == OPCODES["literal"] + if ctx.peek_code(nextidx + 1) == OPCODE_LITERAL: # tail starts with a literal. skip positions where # the rest of the pattern cannot possibly match chr = ctx.peek_code(nextidx + 2) @@ -528,7 +529,7 @@ ctx.has_matched = ctx.NOT_MATCHED return True ctx.skip_char(count) - if ctx.peek_code(ctx.peek_code(1) + 1) == 1: # OPCODES["success"] + if ctx.peek_code(ctx.peek_code(1) + 1) == OPCODE_SUCCESS: # tail is empty. we're finished ctx.state.string_position = ctx.string_position ctx.has_matched = ctx.MATCHED From arigo at codespeak.net Mon Jun 14 12:20:56 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jun 2010 12:20:56 +0200 (CEST) Subject: [pypy-svn] r75387 - pypy/branch/multijit-4/pypy/jit/metainterp/test Message-ID: <20100614102056.35BB5282BDC@codespeak.net> Author: arigo Date: Mon Jun 14 12:20:54 2010 New Revision: 75387 Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_list.py Log: Passing tests. Modified: pypy/branch/multijit-4/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/branch/multijit-4/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/branch/multijit-4/pypy/jit/metainterp/test/test_list.py Mon Jun 14 12:20:54 2010 @@ -143,6 +143,51 @@ assert res == 7 self.check_loops(call=0) + def test_fold_getitem_1(self): + jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total']) + def f(n): + l = [100, n, 300, n, 500] + total = 0 + pc = n + while True: + jitdriver.can_enter_jit(l=l, pc=pc, n=n, total=total) + jitdriver.jit_merge_point(l=l, pc=pc, n=n, total=total) + total += l[pc] + if total > 10000: + return total + pc -= 1 + if pc < 0: + pc = n + + res = self.meta_interp(f, [4], listops=True) + assert res == f(4) + self.check_loops(call=0) + + def test_fold_getitem_2(self): + jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total', 'x']) + class X: + pass + def f(n): + l = [100, n, 300, n, 500] + total = 0 + x = X() + x.pc = n + while True: + pc = x.pc + jitdriver.can_enter_jit(l=l, pc=pc, n=n, total=total, x=x) + jitdriver.jit_merge_point(l=l, pc=pc, n=n, total=total, x=x) + x.pc = pc + total += l[x.pc] + if total > 10000: + return total + x.pc -= 1 + if x.pc < 0: + x.pc = n + + res = self.meta_interp(f, [4], listops=True) + assert res == f(4) + self.check_loops(call=0, getfield_gc=0) + class TestOOtype(ListTests, OOJitMixin): pass From arigo at codespeak.net Mon Jun 14 13:04:43 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jun 2010 13:04:43 +0200 (CEST) Subject: [pypy-svn] r75388 - in pypy/branch/multijit-4/pypy/rlib/rsre: . test Message-ID: <20100614110443.E3F1F282BEC@codespeak.net> Author: arigo Date: Mon Jun 14 13:04:42 2010 New Revision: 75388 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py Log: Depressingly small gains. Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py Mon Jun 14 13:04:42 2010 @@ -14,6 +14,7 @@ from pypy.rlib.rsre.rsre_char import OPCODE_INFO, MAXREPEAT from pypy.rlib.rsre.rsre_char import OPCODE_SUCCESS, OPCODE_LITERAL from pypy.rlib.unroll import unrolling_iterable +from pypy.rlib.debug import make_sure_not_modified #### Core classes @@ -212,42 +213,59 @@ string_position += 1 return False +from pypy.rlib.jit import JitDriver, unroll_safe +rsrejitdriver = JitDriver(greens=['i', 'overlap_offset', 'pattern_codes'], + reds=['string_position', 'end', 'state'], + can_inline=lambda *args: False) + def fast_search(state, pattern_codes): """Skips forward in a string as fast as possible using information from an optimization info block.""" # pattern starts with a known prefix # <5=length> <6=skip> <7=prefix data> - flags = pattern_codes[2] prefix_len = pattern_codes[5] - assert prefix_len >= 0 - prefix_skip = pattern_codes[6] # don't really know what this is good for - assert prefix_skip >= 0 - prefix = pattern_codes[7:7 + prefix_len] overlap_offset = 7 + prefix_len - 1 assert overlap_offset >= 0 - pattern_offset = pattern_codes[1] + 1 - assert pattern_offset >= 0 i = 0 string_position = state.string_position end = state.end while string_position < end: while True: + rsrejitdriver.can_enter_jit( + pattern_codes=pattern_codes, + i=i, + string_position=string_position, + end=end, + state=state, + overlap_offset=overlap_offset) + rsrejitdriver.jit_merge_point( + pattern_codes=pattern_codes, + i=i, + string_position=string_position, + end=end, + state=state, + overlap_offset=overlap_offset) char_ord = state.get_char_ord(string_position) - if char_ord != prefix[i]: + if char_ord != pattern_codes[7+i]: if i == 0: break else: i = pattern_codes[overlap_offset + i] else: i += 1 + prefix_len = pattern_codes[5] if i == prefix_len: # found a potential match + prefix_skip = pattern_codes[6] state.start = string_position + 1 - prefix_len state.string_position = string_position + 1 \ - prefix_len + prefix_skip + flags = pattern_codes[2] if flags & SRE_INFO_LITERAL: return True # matched all of pure literal pattern + pattern_offset = pattern_codes[1] + 1 start = pattern_offset + 2 * prefix_skip + assert start >= 0 if match(state, pattern_codes, start): return True i = pattern_codes[overlap_offset + i] @@ -255,9 +273,11 @@ string_position += 1 return False + at unroll_safe def match(state, pattern_codes, pstart=0): # Optimization: Check string length. pattern_codes[3] contains the # minimum length for a string to possibly match. + make_sure_not_modified(pattern_codes) if pattern_codes[pstart] == OPCODE_INFO and pattern_codes[pstart+3] > 0: # <1=skip> <2=flags> <3=min> if state.end - state.string_position < pattern_codes[pstart+3]: @@ -275,6 +295,7 @@ state.context_stack.pop() return has_matched == MatchContext.MATCHED + at unroll_safe def dispatch_loop(context): """Returns MATCHED if the current context matches, NOT_MATCHED if it doesn't and UNDECIDED if matching is not finished, ie must be resumed after child @@ -478,26 +499,8 @@ # Initialize the actual backtracking if count >= mincount: - # - ok = True - nextidx = ctx.peek_code(1) - if ctx.peek_code(nextidx + 1) == OPCODE_LITERAL: - # tail starts with a literal. skip positions where - # the rest of the pattern cannot possibly match - chr = ctx.peek_code(nextidx + 2) - if ctx.at_end(): - ctx.skip_char(-1) - count -= 1 - ok = count >= mincount - while ok: - if ctx.peek_char() == chr: - break - ctx.skip_char(-1) - count -= 1 - ok = count >= mincount - # - - if ok: + count = quickly_skip_unmatchable_positions(ctx, count, mincount) + if count >= mincount: ctx.state.string_position = ctx.string_position ctx.push_new_context(ctx.peek_code(1) + 1) ctx.backup_value(mincount) @@ -509,6 +512,23 @@ ctx.has_matched = ctx.NOT_MATCHED return True +def quickly_skip_unmatchable_positions(ctx, count, mincount): + # this is only an optimization + nextidx = ctx.peek_code(1) + if ctx.peek_code(nextidx + 1) == OPCODE_LITERAL: + # tail starts with a literal. skip positions where + # the rest of the pattern cannot possibly match + chr = ctx.peek_code(nextidx + 2) + if ctx.at_end(): + ctx.skip_char(-1) + count -= 1 + while count >= mincount: + if ctx.peek_char() == chr: + break + ctx.skip_char(-1) + count -= 1 + return count + def op_min_repeat_one(ctx): # match repeated sequence (minimizing) # <1=min> <2=max> item tail @@ -859,24 +879,28 @@ count = function(ctx, real_maxcount) break else: - # This is a general solution, a bit hackisch, but works - code_position = ctx.code_position - count = 0 - ctx.skip_code(4) - reset_position = ctx.code_position - while count < real_maxcount: - # this works because the single character pattern is followed by - # a success opcode - ctx.code_position = reset_position - opcode_dispatch_table[code](ctx) - if ctx.has_matched == ctx.NOT_MATCHED: - break - count += 1 - ctx.has_matched = ctx.UNDECIDED - ctx.code_position = code_position + count = general_count_repetitions(ctx, real_maxcount, code) ctx.string_position = string_position return count +def general_count_repetitions(ctx, real_maxcount, code): + # This is a general solution, a bit hackisch, but works + code_position = ctx.code_position + count = 0 + ctx.skip_code(4) + reset_position = ctx.code_position + while count < real_maxcount: + # this works because the single character pattern is followed by + # a success opcode + ctx.code_position = reset_position + opcode_dispatch_table[code](ctx) + if ctx.has_matched == ctx.NOT_MATCHED: + break + count += 1 + ctx.has_matched = ctx.UNDECIDED + ctx.code_position = code_position + return count + opcode_dispatch_table = [ op_failure, op_success, op_any, op_any_all, Modified: pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py Mon Jun 14 13:04:42 2010 @@ -1,5 +1,6 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.rsre import rsre +from pypy.rlib.nonconst import NonConstant import os, time @@ -24,9 +25,13 @@ def search_in_file(filename): data = read(filename) p = 0 + if NonConstant(True): + r = r_code1 + else: + r = [] while True: state = rsre.SimpleStringState(data, p) - res = state.search(r_code1) + res = state.search(r) if not res: break groups = state.create_regs(1) @@ -50,6 +55,10 @@ def target(*args): return entry_point, None +from pypy.jit.codewriter.policy import JitPolicy +def jitpolicy(driver): + return JitPolicy() + # _____ Pure Python equivalent _____ if __name__ == '__main__': From jcreigh at codespeak.net Mon Jun 14 17:15:54 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 17:15:54 +0200 (CEST) Subject: [pypy-svn] r75390 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100614151554.07630282BE0@codespeak.net> Author: jcreigh Date: Mon Jun 14 17:15:53 2010 New Revision: 75390 Added: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/arch.py Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py Log: create file arch.py to contain arch-specific constants. Add IS_X86_32 and IS_X86_64 convenience constants Added: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/arch.py ============================================================================== --- (empty file) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/arch.py Mon Jun 14 17:15:53 2010 @@ -0,0 +1,15 @@ +# Constants that depend on whether we are on 32-bit or 64-bit + +import sys +if sys.maxint == (2**31 - 1): + WORD = 4 + FRAME_FIXED_SIZE = 5 # ebp + ebx + esi + edi + force_index = 5 words + FORCE_INDEX_OFS = -4*WORD + IS_X86_32 = True + IS_X86_64 = False +else: + WORD = 8 + FRAME_FIXED_SIZE = 7 + FORCE_INDEX_OFS = -6*WORD + IS_X86_32 = False + IS_X86_64 = True Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Mon Jun 14 17:15:53 2010 @@ -7,9 +7,10 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.annlowlevel import llhelper from pypy.tool.uid import fixid -from pypy.jit.backend.x86.regalloc import RegAlloc, WORD,\ - X86RegisterManager, X86XMMRegisterManager, get_ebp_ofs, FRAME_FIXED_SIZE,\ - FORCE_INDEX_OFS +from pypy.jit.backend.x86.regalloc import RegAlloc, \ + X86RegisterManager, X86XMMRegisterManager, get_ebp_ofs + +from pypy.jit.backend.x86.arch import FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64 from pypy.jit.backend.x86.regloc import (eax, ecx, edx, ebx, esp, ebp, esi, edi, @@ -226,9 +227,9 @@ for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8 mc.MOVSD_sx((WORD*2)+8*i, i) mc.SUB(edx, eax) # compute the size we want - if WORD == 4: + if IS_X86_32: mc.MOV_sr(WORD, edx.value) # save it as the new argument - elif WORD == 8: + elif IS_X86_64: # FIXME: We can't just clobber rdi like this, can we? mc.MOV_rr(edi.value, edx.value) @@ -390,7 +391,7 @@ mc.RET() def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth): - if WORD == 8: + if IS_X86_64: return self._assemble_bootstrap_direct_call_64(arglocs, jmpadr, stackdepth) # XXX pushing ebx esi and edi is a bit pointless, since we store # all regsiters anyway, for the case of guard_not_forced @@ -607,9 +608,9 @@ def genop_cmp(self, op, arglocs, result_loc): self.mc.UCOMISD(arglocs[0], arglocs[1]) tmp1 = result_loc.lowest8bits() - if WORD == 4: + if IS_X86_32: tmp2 = result_loc.higher8bits() - elif WORD == 8: + elif IS_X86_64: tmp2 = X86_64_SCRATCH_REG.lowest8bits() self.mc.SET_ir(rx86.Conditions[cond], tmp1.value) @@ -662,7 +663,7 @@ @specialize.arg(5) def _emit_call(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): - if WORD == 8: + if IS_X86_64: return self._emit_call_64(x, arglocs, start, tmp, force_mc, mc) if not force_mc: @@ -912,12 +913,10 @@ genop_virtual_ref = genop_same_as def genop_int_mod(self, op, arglocs, resloc): - if WORD == 4: + if IS_X86_32: self.mc.CDQ() - elif WORD == 8: + elif IS_X86_64: self.mc.CQO() - else: - raise AssertionError("Can't happen") self.mc.IDIV_r(ecx.value) @@ -1482,9 +1481,9 @@ # it's ok because failure_recovery_func is not calling anything more # XXX - if mc.WORD == 4: + if IS_X86_32: mc.PUSH(ebx) - elif mc.WORD == 8: + elif IS_X86_64: mc.MOV(edi, ebx) # XXX: Correct to only align the stack on 64-bit? mc.AND_ri(esp.value, -16) @@ -1570,7 +1569,7 @@ self._emit_call(x, arglocs, 2, tmp=tmp) - if isinstance(resloc, StackLoc) and resloc.width == 8 and WORD == 4: + if isinstance(resloc, StackLoc) and resloc.width == 8 and IS_X86_32: self.mc.FSTP_b(resloc.value) elif size == 1: self.mc.AND(eax, imm(0xff)) @@ -1614,7 +1613,7 @@ assert 0 < offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if WORD == 4 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: + if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: self.mc.FSTP_b(result_loc.value) else: assert result_loc is eax or result_loc is xmm0 or result_loc is None @@ -1639,7 +1638,11 @@ for i in range(len(arglocs)-1, -1, -1): mc.PUSH(arglocs[i]) - if WORD == 8: + if IS_X86_64: + # We clobber these registers to pass the arguments, but that's + # okay, because consider_cond_call_gc_wb makes sure that any + # caller-save registers with values in them are present in arglocs, + # so they are saved on the stack above and restored below mc.MOV_rs(edi.value, 0) mc.MOV_rs(esi.value, 8) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py Mon Jun 14 17:15:53 2010 @@ -6,12 +6,12 @@ from pypy.jit.backend.x86.regloc import LocationCodeBuilder from pypy.rlib.rmmap import PTR, alloc, free from pypy.rlib.debug import make_sure_not_resized -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 # XXX: Seems nasty to change the superclass of InMemoryCodeBuilder like this -if WORD == 4: +if IS_X86_32: codebuilder_cls = X86_32_CodeBuilder -elif WORD == 8: +elif IS_X86_64: codebuilder_cls = X86_64_CodeBuilder class InMemoryCodeBuilder(codebuilder_cls, LocationCodeBuilder): @@ -108,9 +108,9 @@ return False # log the executable name from pypy.jit.backend.hlinfo import highleveljitinfo - if WORD == 4: + if IS_X86_32: os.write(self.log_fd, 'BACKEND x86\n') - elif WORD == 8: + elif IS_X86_64: os.write(self.log_fd, 'BACKEND x86_64\n') if highleveljitinfo.sys_executable: os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % ( Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Mon Jun 14 17:15:53 2010 @@ -16,28 +16,13 @@ from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\ TempBox +from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, IS_X86_32, IS_X86_64 -# XXX -import sys -if sys.maxint == (2**31 - 1): - WORD = 4 - FRAME_FIXED_SIZE = 5 # ebp + ebx + esi + edi + force_index = 5 words - FORCE_INDEX_OFS = -4*WORD - width_of_type = { - INT : 1, - REF : 1, - FLOAT : 2, - } -else: - WORD = 8 - FRAME_FIXED_SIZE = 7 - FORCE_INDEX_OFS = -6*WORD - width_of_type = { - INT : 1, - REF : 1, - FLOAT : 1, - } - +width_of_type = { + INT : 1, + REF : 1, + FLOAT : (2 if IS_X86_32 else 1), +} class X86RegisterManager(RegisterManager): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Mon Jun 14 17:15:53 2010 @@ -3,7 +3,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp import history, compile from pypy.jit.backend.x86.assembler import Assembler386 -from pypy.jit.backend.x86.regalloc import FORCE_INDEX_OFS +from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS from pypy.jit.backend.x86.profagent import ProfileAgent from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU from pypy.jit.backend.x86 import regloc Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Mon Jun 14 17:15:53 2010 @@ -4,11 +4,12 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT from pypy.rlib.rarithmetic import intmask from pypy.rpython.lltypesystem import lltype, llmemory, rffi -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.arch import WORD from pypy.jit.backend.detect_cpu import getcpuclass ACTUAL_CPU = getcpuclass() +py.test.skip() class FakeCPU: rtyper = None supports_floats = True Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py Mon Jun 14 17:15:53 2010 @@ -9,7 +9,8 @@ from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription from pypy.jit.backend.detect_cpu import getcpuclass -from pypy.jit.backend.x86.regalloc import RegAlloc, WORD, FRAME_FIXED_SIZE +from pypy.jit.backend.x86.regalloc import RegAlloc +from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.annlowlevel import llhelper Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_recompilation.py Mon Jun 14 17:15:53 2010 @@ -1,5 +1,5 @@ from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 class TestRecompilation(BaseTestRegalloc): def test_compile_bridge_not_deeper(self): @@ -51,7 +51,7 @@ new = descr._x86_bridge_frame_depth assert descr._x86_bridge_param_depth == 0 # XXX: Maybe add enough ops to force stack on 64-bit as well? - if WORD == 4: + if IS_X86_32: assert new > previous self.cpu.set_future_value_int(0, 0) fail = self.run(loop) @@ -113,7 +113,7 @@ loop_frame_depth = loop.token._x86_frame_depth assert loop.token._x86_param_depth == 0 # XXX: Maybe add enough ops to force stack on 64-bit as well? - if WORD == 4: + if IS_X86_32: assert guard_op.descr._x86_bridge_frame_depth > loop_frame_depth assert guard_op.descr._x86_bridge_param_depth == 0 self.cpu.set_future_value_int(0, 0) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Mon Jun 14 17:15:53 2010 @@ -8,7 +8,7 @@ from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.detect_cpu import getcpuclass -from pypy.jit.backend.x86.regalloc import RegAlloc, WORD, X86RegisterManager,\ +from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\ FloatConstants from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.lltypesystem import lltype, llmemory, rffi Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Mon Jun 14 17:15:53 2010 @@ -4,7 +4,7 @@ from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Box, BasicFailDescr) from pypy.jit.backend.detect_cpu import getcpuclass -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.arch import WORD from pypy.jit.backend.llsupport import symbolic from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.executor import execute Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_symbolic_x86.py Mon Jun 14 17:15:53 2010 @@ -1,7 +1,7 @@ import py from pypy.jit.backend.llsupport.symbolic import * from pypy.rpython.lltypesystem import lltype, rffi -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.arch import WORD # This test file is here and not in llsupport/test/ because it checks # that we get correct numbers for a 32-bit machine. From jcreigh at codespeak.net Mon Jun 14 17:19:20 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 17:19:20 +0200 (CEST) Subject: [pypy-svn] r75391 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100614151920.805CE282BE0@codespeak.net> Author: jcreigh Date: Mon Jun 14 17:19:19 2010 New Revision: 75391 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Log: grr. remove line accidentally commited in r75390 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Mon Jun 14 17:19:19 2010 @@ -9,7 +9,6 @@ ACTUAL_CPU = getcpuclass() -py.test.skip() class FakeCPU: rtyper = None supports_floats = True From fijal at codespeak.net Mon Jun 14 18:36:28 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jun 2010 18:36:28 +0200 (CEST) Subject: [pypy-svn] r75392 - in pypy/release/1.3.x: . pypy/lib/app_test/ctypes_tests Message-ID: <20100614163628.E7551282BE0@codespeak.net> Author: fijal Date: Mon Jun 14 18:36:27 2010 New Revision: 75392 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py Log: Merge r75366 from trunk Modified: pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/release/1.3.x/pypy/lib/app_test/ctypes_tests/test_functions.py Mon Jun 14 18:36:27 2010 @@ -217,7 +217,7 @@ class X(Structure): _fields_ = [("y", c_int)] - raises(TypeError, f, X()) #cannot convert parameter + raises(ArgumentError, f, X()) #cannot convert parameter ################################################################ def test_shorts(self): From jcreigh at codespeak.net Mon Jun 14 18:48:41 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 18:48:41 +0200 (CEST) Subject: [pypy-svn] r75393 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100614164841.54DA9282BF3@codespeak.net> Author: jcreigh Date: Mon Jun 14 18:48:39 2010 New Revision: 75393 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Log: fix test_assembler.py for 64-bit Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Mon Jun 14 18:48:39 2010 @@ -4,8 +4,9 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT from pypy.rlib.rarithmetic import intmask from pypy.rpython.lltypesystem import lltype, llmemory, rffi -from pypy.jit.backend.x86.arch import WORD +from pypy.jit.backend.x86.arch import WORD, IS_X86_32, IS_X86_64 from pypy.jit.backend.detect_cpu import getcpuclass +from pypy.jit.backend.x86.regalloc import X86RegisterManager, X86_64_RegisterManager, X86XMMRegisterManager, X86_64_XMMRegisterManager ACTUAL_CPU = getcpuclass() @@ -127,6 +128,9 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) def get_random_float(): + # Returns , , + # NB: on 64-bit, will be the entire float and + # will be random garbage from malloc! assert withfloats value = random.random() - 0.5 # make sure it fits into 64 bits @@ -134,9 +138,16 @@ rffi.cast(rffi.DOUBLEP, tmp)[0] = value return rffi.cast(rffi.DOUBLEP, tmp)[0], tmp[0], tmp[1] + if IS_X86_32: + main_registers = X86RegisterManager.all_regs + xmm_registers = X86XMMRegisterManager.all_regs + elif IS_X86_64: + main_registers = X86_64_RegisterManager.all_regs + xmm_registers = X86_64_XMMRegisterManager.all_regs + # memory locations: 26 integers, 26 pointers, 26 floats # main registers: half of them as signed and the other half as ptrs - # xmm registers: all floats, from xmm0 to xmm7 + # xmm registers: all floats, from xmm0 to xmm(7|15) # holes: 8 locations = [] baseloc = 4 @@ -150,18 +161,17 @@ content = ([('int', locations.pop()) for _ in range(26)] + [('ptr', locations.pop()) for _ in range(26)] + [(['int', 'ptr'][random.randrange(0, 2)], reg) - for reg in [eax, ecx, edx, ebx, esi, edi]]) + for reg in main_registers]) if withfloats: content += ([('float', locations.pop()) for _ in range(26)] + - [('float', reg) for reg in [xmm0, xmm1, xmm2, xmm3, - xmm4, xmm5, xmm6, xmm7]]) + [('float', reg) for reg in xmm_registers]) for i in range(8): content.append(('hole', None)) random.shuffle(content) # prepare the expected target arrays, the descr_bytecode, # the 'registers' and the 'stack' arrays according to 'content' - xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+9, flavor='raw') + xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+ACTUAL_CPU.NUM_REGS+1, flavor='raw') registers = rffi.ptradd(xmmregisters, 16) stacklen = baseloc + 10 stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw') @@ -186,11 +196,17 @@ expected_floats[i] = value kind = Assembler386.DESCR_FLOAT if isinstance(loc, RegLoc): - xmmregisters[2*loc.value] = lo - xmmregisters[2*loc.value+1] = hi + if WORD == 4: + xmmregisters[2*loc.value] = lo + xmmregisters[2*loc.value+1] = hi + elif WORD == 8: + xmmregisters[loc.value] = lo else: - write_in_stack(loc, hi) - write_in_stack(loc+1, lo) + if WORD == 4: + write_in_stack(loc, hi) + write_in_stack(loc+1, lo) + elif WORD == 8: + write_in_stack(loc, lo) else: if kind == 'int': value = get_random_int() @@ -228,8 +244,8 @@ for i in range(len(descr_bytecode)): assert 0 <= descr_bytecode[i] <= 255 descr_bytes[i] = rffi.cast(rffi.UCHAR, descr_bytecode[i]) - registers[8] = rffi.cast(rffi.LONG, descr_bytes) - registers[ebp.value] = rffi.cast(rffi.LONG, stack) + 4*stacklen + registers[ACTUAL_CPU.NUM_REGS] = rffi.cast(rffi.LONG, descr_bytes) + registers[ebp.value] = rffi.cast(rffi.LONG, stack) + WORD*stacklen # run! assembler = Assembler386(FakeCPU()) From afa at codespeak.net Mon Jun 14 18:55:27 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 14 Jun 2010 18:55:27 +0200 (CEST) Subject: [pypy-svn] r75394 - pypy/trunk/pypy/translator/platform Message-ID: <20100614165527.C8747282BF3@codespeak.net> Author: afa Date: Mon Jun 14 18:55:26 2010 New Revision: 75394 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: add and embed a manifest file in the main program, it was missing from the Makefile when --shared is used. Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Mon Jun 14 18:55:26 2010 @@ -287,7 +287,9 @@ 'int main(int argc, char* argv[]) ' '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@') m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'], - '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@') + ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFESTFILE:$*.manifest', + 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', + ]) return m From fijal at codespeak.net Mon Jun 14 18:56:31 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jun 2010 18:56:31 +0200 (CEST) Subject: [pypy-svn] r75395 - in pypy/release/1.3.x: . pypy/translator/platform Message-ID: <20100614165631.75FB5282BF3@codespeak.net> Author: fijal Date: Mon Jun 14 18:56:30 2010 New Revision: 75395 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/translator/platform/windows.py Log: Merge 75394 from trunk Modified: pypy/release/1.3.x/pypy/translator/platform/windows.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/windows.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/windows.py Mon Jun 14 18:56:30 2010 @@ -287,7 +287,9 @@ 'int main(int argc, char* argv[]) ' '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@') m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'], - '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@') + ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFESTFILE:$*.manifest', + 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', + ]) return m From fijal at codespeak.net Mon Jun 14 19:02:52 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jun 2010 19:02:52 +0200 (CEST) Subject: [pypy-svn] r75396 - in pypy/release/1.3.x: . pypy/tool/release Message-ID: <20100614170252.EC21A282BE0@codespeak.net> Author: fijal Date: Mon Jun 14 19:02:51 2010 New Revision: 75396 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/tool/release/pack.py Log: Merge 75382 from trunk Modified: pypy/release/1.3.x/pypy/tool/release/pack.py ============================================================================== --- pypy/release/1.3.x/pypy/tool/release/pack.py (original) +++ pypy/release/1.3.x/pypy/tool/release/pack.py Mon Jun 14 19:02:51 2010 @@ -10,7 +10,7 @@ def filenames_from_platform(platform): if platform == 'win32': files = [goal_dir / 'pypy-c.exe'] - dll = goal_dir.join('pypy-c.dll') + dll = goal_dir.join('libpypy-c.exe.dll') if dll.check(): files.append(dll) else: From jcreigh at codespeak.net Mon Jun 14 19:24:41 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 19:24:41 +0200 (CEST) Subject: [pypy-svn] r75397 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100614172441.AF10F282BE0@codespeak.net> Author: jcreigh Date: Mon Jun 14 19:24:40 2010 New Revision: 75397 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Log: fix test_regalloc.py for 64-bit Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Mon Jun 14 19:24:40 2010 @@ -10,6 +10,7 @@ from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\ FloatConstants +from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.annlowlevel import llhelper @@ -93,13 +94,20 @@ def f2(x, y): return x*y + def f10(*args): + assert len(args) == 10 + return sum(args) + F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) F2PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*2, lltype.Signed)) + F10PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*10, lltype.Signed)) f1ptr = llhelper(F1PTR, f1) f2ptr = llhelper(F2PTR, f2) + f10ptr = llhelper(F10PTR, f10) f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT) f2_calldescr = cpu.calldescrof(F2PTR.TO, F2PTR.TO.ARGS, F2PTR.TO.RESULT) + f10_calldescr = cpu.calldescrof(F10PTR.TO, F10PTR.TO.ARGS, F10PTR.TO.RESULT) namespace = locals().copy() type_system = 'lltype' @@ -541,6 +549,12 @@ assert self.getints(9) == [0, 1, 1, 1, 1, 1, 1, 1, 1] class TestRegAllocCallAndStackDepth(BaseTestRegalloc): + def expected_param_depth(self, num_args): + # Assumes the arguments are all non-float + if IS_X86_32: + return num_args + elif IS_X86_64: + return max(num_args - 6, 0) def test_one_call(self): ops = ''' @@ -550,7 +564,7 @@ ''' loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9, 9]) assert self.getints(11) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9] - assert loop.token._x86_param_depth == 1 + assert loop.token._x86_param_depth == self.expected_param_depth(1) def test_two_calls(self): ops = ''' @@ -561,8 +575,18 @@ ''' loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9, 9]) assert self.getints(11) == [5*7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9] - assert loop.token._x86_param_depth == 2 - + assert loop.token._x86_param_depth == self.expected_param_depth(2) + + def test_call_many_arguments(self): + ops = ''' + [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9] + i10 = call(ConstClass(f10ptr), i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, descr=f10_calldescr) + finish(i10) + ''' + loop = self.interpret(ops, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + assert self.getint(0) == 55 + assert loop.token._x86_param_depth == self.expected_param_depth(10) + def test_bridge_calls_1(self): ops = ''' [i0, i1] @@ -579,7 +603,7 @@ ''' bridge = self.attach_bridge(ops, loop, -2) - assert loop.operations[-2].descr._x86_bridge_param_depth == 2 + assert loop.operations[-2].descr._x86_bridge_param_depth == self.expected_param_depth(2) self.cpu.set_future_value_int(0, 4) self.cpu.set_future_value_int(1, 7) @@ -602,7 +626,7 @@ ''' bridge = self.attach_bridge(ops, loop, -2) - assert loop.operations[-2].descr._x86_bridge_param_depth == 2 + assert loop.operations[-2].descr._x86_bridge_param_depth == self.expected_param_depth(2) self.cpu.set_future_value_int(0, 4) self.cpu.set_future_value_int(1, 7) From jcreigh at codespeak.net Mon Jun 14 20:17:52 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 20:17:52 +0200 (CEST) Subject: [pypy-svn] r75398 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100614181752.28809282BF3@codespeak.net> Author: jcreigh Date: Mon Jun 14 20:17:49 2010 New Revision: 75398 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Log: remove width_of_type dict that was only used in one place Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Mon Jun 14 20:17:49 2010 @@ -18,12 +18,6 @@ TempBox from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, IS_X86_32, IS_X86_64 -width_of_type = { - INT : 1, - REF : 1, - FLOAT : (2 if IS_X86_32 else 1), -} - class X86RegisterManager(RegisterManager): box_types = [INT, REF] @@ -120,17 +114,12 @@ return RegisterManager.after_call(self, v) class X86FrameManager(FrameManager): - @staticmethod def frame_pos(i, box_type): - size = width_of_type[box_type] - if size == 1: - return StackLoc(i, get_ebp_ofs(i), size, box_type) - elif size == 2: - return StackLoc(i, get_ebp_ofs(i+1), size, box_type) + if IS_X86_32 and box_type == FLOAT: + return StackLoc(i, get_ebp_ofs(i+1), 2, box_type) else: - print "Unimplemented size %d" % i - raise NotImplementedError("unimplemented size %d" % i) + return StackLoc(i, get_ebp_ofs(i), 1, box_type) class RegAlloc(object): exc = False From jcreigh at codespeak.net Mon Jun 14 21:00:54 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 21:00:54 +0200 (CEST) Subject: [pypy-svn] r75399 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100614190054.79492282BF3@codespeak.net> Author: jcreigh Date: Mon Jun 14 21:00:52 2010 New Revision: 75399 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py Log: fix test_regalloc2.py for 64-bit Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py Mon Jun 14 21:00:52 2010 @@ -3,6 +3,7 @@ BoxPtr, ConstPtr, BasicFailDescr, LoopToken from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.detect_cpu import getcpuclass +from pypy.jit.backend.x86.arch import WORD CPU = getcpuclass() def test_bug_rshift(): @@ -282,5 +283,8 @@ assert cpu.get_latest_value_int(16) == -57344 assert cpu.get_latest_value_int(17) == 1 assert cpu.get_latest_value_int(18) == -1 - assert cpu.get_latest_value_int(19) == -2147483648 + if WORD == 4: + assert cpu.get_latest_value_int(19) == -2147483648 + elif WORD == 8: + assert cpu.get_latest_value_int(19) == 19327352832 assert cpu.get_latest_value_int(20) == -49 From jcreigh at codespeak.net Mon Jun 14 22:37:16 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Mon, 14 Jun 2010 22:37:16 +0200 (CEST) Subject: [pypy-svn] r75400 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100614203716.772B9282BF3@codespeak.net> Author: jcreigh Date: Mon Jun 14 22:37:13 2010 New Revision: 75400 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: add a helper to x86 to define the common mod/rm modes to help avoid boilerplate code when defining instructions Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Mon Jun 14 22:37:13 2010 @@ -420,48 +420,6 @@ # ------------------------------ MOV ------------------------------ MOV_ri = insn(rex_w, register(1), '\xB8', immediate(2, 'q')) - MOV_rr = insn(rex_w, '\x89', register(2,8), register(1), '\xC0') - MOV_bi = insn(rex_w, '\xC7', stack_bp(1), immediate(2)) - MOV_br = insn(rex_w, '\x89', register(2,8), stack_bp(1)) - MOV_rb = insn(rex_w, '\x8B', register(1,8), stack_bp(2)) - MOV_sr = insn(rex_w, '\x89', register(2,8), stack_sp(1)) - MOV_rs = insn(rex_w, '\x8B', register(1,8), stack_sp(2)) - - # "MOV reg1, [reg2+offset]" and the opposite direction - MOV_rm = insn(rex_w, '\x8B', register(1,8), mem_reg_plus_const(2)) - MOV_mr = insn(rex_w, '\x89', register(2,8), mem_reg_plus_const(1)) - MOV_mi = insn(rex_w, '\xC7', orbyte(0<<3), mem_reg_plus_const(1), - immediate(2, 'i')) - - # "MOV reg1, [reg2+reg3*scale+offset]" and the opposite direction - MOV_ra = insn(rex_w, '\x8B', register(1,8), - mem_reg_plus_scaled_reg_plus_const(2)) - MOV_ar = insn(rex_w, '\x89', register(2,8), - mem_reg_plus_scaled_reg_plus_const(1)) - MOV_ai = insn(rex_w, '\xC7', orbyte(0<<3), mem_reg_plus_scaled_reg_plus_const(1), immediate(2)) - - - MOV8_mr = insn(rex_w, '\x88', byte_register(2, 8), mem_reg_plus_const(1)) - MOV8_ar = insn(rex_w, '\x88', byte_register(2, 8), mem_reg_plus_scaled_reg_plus_const(1)) - MOV8_mi = insn(rex_w, '\xC6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) - MOV8_ai = insn(rex_w, '\xC6', orbyte(0<<3), mem_reg_plus_scaled_reg_plus_const(1), immediate(2, 'b')) - - MOVZX8_rr = insn(rex_w, '\x0F\xB6', register(1,8), byte_register(2), '\xC0') - MOVZX8_rm = insn(rex_w, '\x0F\xB6', register(1,8), mem_reg_plus_const(2)) - MOVZX8_ra = insn(rex_w, '\x0F\xB6', register(1,8), mem_reg_plus_scaled_reg_plus_const(2)) - - MOVZX16_rm = insn(rex_w, '\x0F\xB7', register(1,8), mem_reg_plus_const(2)) - MOVZX16_ra = insn(rex_w, '\x0F\xB7', register(1,8), mem_reg_plus_scaled_reg_plus_const(2)) - - # FIXME: Only difference between MOV32 and MOV instructions is rex_nw instead of rex_w - MOV32_ra = insn(rex_nw, '\x8B', register(1,8), - mem_reg_plus_scaled_reg_plus_const(2)) - MOV32_ar = insn(rex_nw, '\x89', register(2,8), - mem_reg_plus_scaled_reg_plus_const(1)) - MOV32_rm = insn(rex_nw, '\x8B', register(1,8), mem_reg_plus_const(2)) - MOV32_mr = insn(rex_nw, '\x89', register(2,8), mem_reg_plus_const(1)) - MOV32_mi = insn(rex_nw, '\xC7', orbyte(0<<3), mem_reg_plus_const(1), - immediate(2, 'i')) # ------------------------------ Arithmetic ------------------------------ @@ -524,7 +482,9 @@ CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) CALL_b = insn('\xFF', orbyte(2<<3), stack_bp(1)) - XCHG_rm = insn(rex_w, '\x87', register(1,8), mem_reg_plus_const(2)) + # XXX: Only here for testing purposes..."as" happens the encode the + # registers in the opposite order that we would otherwise do in a + # register-register exchange XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') JMP_l = insn('\xE9', relative(1)) @@ -548,42 +508,6 @@ # ------------------------------ SSE2 ------------------------------ - MOVSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1,8), register(2), - '\xC0') - MOVSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1,8), stack_bp(2)) - MOVSD_bx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2,8), stack_bp(1)) - MOVSD_xs = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1,8), stack_sp(2)) - MOVSD_sx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2,8), stack_sp(1)) - MOVSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1,8), - mem_reg_plus_const(2)) - MOVSD_xa = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1,8), mem_reg_plus_scaled_reg_plus_const(2)) - MOVSD_mx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2,8), - mem_reg_plus_const(1)) - MOVSD_ax = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2,8), mem_reg_plus_scaled_reg_plus_const(1)) - - - # Arithmetic - ADDSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), register(2), '\xC0') - ADDSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), stack_bp(2)) - ADDSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), mem_reg_plus_const(2)) - - SUBSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), register(2), '\xC0') - SUBSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), stack_bp(2)) - SUBSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), mem_reg_plus_const(2)) - - MULSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), register(2), '\xC0') - MULSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), stack_bp(2)) - MULSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), mem_reg_plus_const(2)) - - DIVSD_xx = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), register(2), '\xC0') - DIVSD_xb = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), stack_bp(2)) - DIVSD_xm = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), mem_reg_plus_const(2)) - - # Comparision - UCOMISD_xx = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), register(2), '\xC0') - UCOMISD_xb = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), stack_bp(2)) - UCOMISD_xm = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), mem_reg_plus_const(2)) - # Conversion CVTSI2SD_xr = xmminsn('\xF2', rex_w, '\x0F\x2A', register(1, 8), register(2), '\xC0') CVTSI2SD_xb = xmminsn('\xF2', rex_w, '\x0F\x2A', register(1, 8), stack_bp(2)) @@ -591,13 +515,6 @@ CVTTSD2SI_rx = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), register(2), '\xC0') CVTTSD2SI_rb = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), stack_bp(2)) - # Bitwise - - XORPD_xx = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), register(2), '\xC0') - XORPD_xm = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), mem_reg_plus_const(2)) - - ANDPD_xm = xmminsn('\x66', rex_nw, '\x0F\x54', register(1, 8), mem_reg_plus_const(2)) - # ------------------------------------------------------------ Conditions = { @@ -623,14 +540,6 @@ class X86_32_CodeBuilder(AbstractX86CodeBuilder): WORD = 4 - # We can do direct memory references on 32-bit - MOV_rj = insn(rex_w, '\x8B', register(1,8), '\x05', immediate(2)) - MOV_jr = insn(rex_w, '\x89', register(2,8), '\x05', immediate(1)) - MOV_ji = insn(rex_w, '\xC7', '\x05', immediate(1), immediate(2)) - MOV8_ji = insn(rex_w, '\xC6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b')) - MOV8_jr = insn(rex_w, '\x88', byte_register(2, 8), '\x05', immediate(1)) - MOVZX8_rj = insn(rex_w, '\x0F\xB6', register(1,8), '\x05', immediate(2)) - CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b')) CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2)) CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) @@ -640,18 +549,6 @@ # displacement is always enough to encode any address CALL_j = AbstractX86CodeBuilder.CALL_l - XCHG_rj = insn(rex_w, '\x87', register(1,8), '\x05', immediate(2)) - - MOVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x10', register(1, 8), '\x05', immediate(2)) - MOVSD_jx = xmminsn('\xF2', rex_nw, '\x0F\x11', register(2, 8), '\x05', immediate(1)) - ADDSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x58', register(1, 8), '\x05', immediate(2)) - SUBSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5C', register(1, 8), '\x05', immediate(2)) - MULSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x59', register(1, 8), '\x05', immediate(2)) - DIVSD_xj = xmminsn('\xF2', rex_nw, '\x0F\x5E', register(1, 8), '\x05', immediate(2)) - UCOMISD_xj = xmminsn('\x66', rex_nw, '\x0F\x2E', register(1, 8), '\x05', immediate(2)) - ANDPD_xj = xmminsn('\x66', rex_nw, '\x0F\x54', register(1, 8), '\x05', immediate(2)) - XORPD_xj = xmminsn('\x66', rex_nw, '\x0F\x57', register(1, 8), '\x05', immediate(2)) - class X86_64_CodeBuilder(AbstractX86CodeBuilder): WORD = 8 @@ -691,6 +588,64 @@ # XXX CALL_j = CALL_l +def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): + def add_insn(code, *modrm): + args = before_modrm + list(modrm) + after_modrm + methname = insnname_template.replace('*', code) + if methname.endswith('_rr') or methname.endswith('_xx'): + args.append('\xC0') + + if regtype == 'XMM': + insn_func = xmminsn(*args) + else: + insn_func = insn(*args) + + if not hasattr(AbstractX86CodeBuilder, methname): + setattr(AbstractX86CodeBuilder, methname, insn_func) + + modrm_argnum = insnname_template.split('_')[1].index('*')+1 + + if regtype == 'GPR': + add_insn('r', register(modrm_argnum)) + elif regtype == 'BYTE': + add_insn('r', byte_register(modrm_argnum)) + elif regtype == 'XMM': + add_insn('x', register(modrm_argnum)) + else: + raise AssertionError("Invalid type") + + add_insn('b', stack_bp(modrm_argnum)) + add_insn('s', stack_sp(modrm_argnum)) + add_insn('m', mem_reg_plus_const(modrm_argnum)) + add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum)) + add_insn('j', '\x05', immediate(modrm_argnum)) + +# Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a +# register +for insnname, rex_type in [('MOV', rex_w), ('MOV32', rex_nw)]: + define_modrm_modes(insnname + '_*r', [rex_type, '\x89', register(2, 8)]) + define_modrm_modes(insnname + '_r*', [rex_type, '\x8B', register(1, 8)]) + define_modrm_modes(insnname + '_*i', [rex_type, '\xC7', orbyte(0<<3)], [immediate(2)]) + +define_modrm_modes('MOV8_*r', [rex_w, '\x88', byte_register(2, 8)], regtype='BYTE') +define_modrm_modes('MOV8_*i', [rex_w, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE') + +define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE') +define_modrm_modes('MOVZX16_r*', [rex_w, '\x0F\xB7', register(1, 8)]) + +define_modrm_modes('MOVSD_x*', ['\xF2', rex_nw, '\x0F\x10', register(1,8)], regtype='XMM') +define_modrm_modes('MOVSD_*x', ['\xF2', rex_nw, '\x0F\x11', register(2,8)], regtype='XMM') + +define_modrm_modes('XCHG_r*', [rex_w, '\x87', register(1, 8)]) + +define_modrm_modes('ADDSD_x*', ['\xF2', rex_nw, '\x0F\x58', register(1, 8)], regtype='XMM') +define_modrm_modes('SUBSD_x*', ['\xF2', rex_nw, '\x0F\x5C', register(1, 8)], regtype='XMM') +define_modrm_modes('MULSD_x*', ['\xF2', rex_nw, '\x0F\x59', register(1, 8)], regtype='XMM') +define_modrm_modes('DIVSD_x*', ['\xF2', rex_nw, '\x0F\x5E', register(1, 8)], regtype='XMM') +define_modrm_modes('UCOMISD_x*', ['\x66', rex_nw, '\x0F\x2E', register(1, 8)], regtype='XMM') +define_modrm_modes('XORPD_x*', ['\x66', rex_nw, '\x0F\x57', register(1, 8)], regtype='XMM') +define_modrm_modes('ANDPD_x*', ['\x66', rex_nw, '\x0F\x54', register(1, 8)], regtype='XMM') + # ____________________________________________________________ # FIXME: What about 32-bit only or 64-bit only instructions? From jcreigh at codespeak.net Tue Jun 15 01:02:02 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 15 Jun 2010 01:02:02 +0200 (CEST) Subject: [pypy-svn] r75401 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100614230202.4C4D0282BE0@codespeak.net> Author: jcreigh Date: Tue Jun 15 01:01:57 2010 New Revision: 75401 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Log: fix 'width' of locations being incorrect on 64-bit Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Tue Jun 15 01:01:57 2010 @@ -532,7 +532,7 @@ if isinstance(loc, RegLoc) and loc.is_xmm: self.mc.SUB_ri(esp.value, 2*WORD) self.mc.MOVSD_sx(0, loc.value) - elif isinstance(loc, StackLoc) and loc.width == 8: + elif WORD == 4 and isinstance(loc, StackLoc) and loc.width == 8: # XXX evil trick self.mc.PUSH_b(get_ebp_ofs(loc.position)) self.mc.PUSH_b(get_ebp_ofs(loc.position + 1)) @@ -543,7 +543,7 @@ if isinstance(loc, RegLoc) and loc.is_xmm: self.mc.MOVSD_xs(loc.value, 0) self.mc.ADD(esp, imm(2*WORD)) - elif isinstance(loc, StackLoc) and loc.width == 8: + elif WORD == 4 and isinstance(loc, StackLoc) and loc.width == 8: # XXX evil trick self.mc.POP_b(get_ebp_ofs(loc.position + 1)) self.mc.POP_b(get_ebp_ofs(loc.position)) @@ -1517,8 +1517,7 @@ for i in range(len(locs)): loc = locs[i] if not isinstance(loc, RegLoc): - if loc.width == 8: - assert isinstance(loc, StackLoc) + if isinstance(loc, StackLoc) and loc.type == FLOAT: mc.MOVSD_xb(xmm0.value, loc.value) adr = self.fail_boxes_float.get_addr_for_num(i) mc.MOVSD(heap(adr), xmm0) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Tue Jun 15 01:01:57 2010 @@ -1,6 +1,7 @@ from pypy.jit.metainterp.history import AbstractValue, ConstInt from pypy.jit.backend.x86 import rx86 from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.backend.x86.arch import WORD # # This module adds support for "locations", which can be either in a Const, @@ -30,13 +31,13 @@ self.position = position self.value = ebp_offset # XXX: Word size hardcoded - self.width = num_words * 4 + self.width = num_words * WORD # One of INT, REF, FLOAT self.type = type def frame_size(self): # XXX: word size - return self.width // 4 + return self.width // WORD def __repr__(self): return '%d(%%ebp)' % (self.value,) @@ -58,7 +59,7 @@ if self.is_xmm: self.width = 8 else: - self.width = 4 + self.width = WORD def __repr__(self): if self.is_xmm: return rx86.R.xmmnames[self.value] @@ -85,8 +86,8 @@ class ImmedLoc(AssemblerLocation): _immutable_ = True - # XXX: word size hardcoded. And does this even make sense for an immediate? - width = 4 + # XXX: Does this even make sense for an immediate? + width = WORD def __init__(self, value): self.value = value @@ -108,8 +109,7 @@ class AddressLoc(AssemblerLocation): _immutable_ = True - # XXX - width = 4 + width = WORD # The address is base_loc + (scaled_loc << scale) + static_offset def __init__(self, base_loc, scaled_loc, scale=0, static_offset=0): assert 0 <= scale < 4 @@ -175,7 +175,7 @@ elif self.WORD == 8 and possible_code2 == 'j': self.MOV_ri(X86_64_SCRATCH_REG.value, val2) getattr(self, name + "_" + possible_code1 + "m")(val1, (X86_64_SCRATCH_REG.value, 0)) - elif self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2) and name != 'MOV': + elif self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2): self.MOV_ri(X86_64_SCRATCH_REG.value, val2) getattr(self, name + "_" + possible_code1 + "r")(val1, X86_64_SCRATCH_REG.value) else: From dan at codespeak.net Tue Jun 15 08:46:50 2010 From: dan at codespeak.net (dan at codespeak.net) Date: Tue, 15 Jun 2010 08:46:50 +0200 (CEST) Subject: [pypy-svn] r75402 - in pypy/trunk/pypy/module/cpyext: . test Message-ID: <20100615064650.7634C282BF6@codespeak.net> Author: dan Date: Tue Jun 15 08:46:48 2010 New Revision: 75402 Modified: pypy/trunk/pypy/module/cpyext/stubs.py pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py pypy/trunk/pypy/module/cpyext/unicodeobject.py Log: Added PyUnicodeAsASCIIString() and test. Modified: pypy/trunk/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/stubs.py (original) +++ pypy/trunk/pypy/module/cpyext/stubs.py Tue Jun 15 08:46:48 2010 @@ -3036,13 +3036,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsASCIIString(space, unicode): - """Encode a Unicode object using ASCII and return the result as Python string - object. Error handling is "strict". Return NULL if an exception was raised - by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject) def PyUnicode_DecodeCharmap(space, s, size, mapping, errors): """Create a Unicode object by decoding size bytes of the encoded string s using Modified: pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_unicodeobject.py Tue Jun 15 08:46:48 2010 @@ -161,3 +161,15 @@ test('\\u0105\\u0107\\u017c\\u017a') test('El Ni\\xf1o') + def test_ascii(self, space, api): + ustr = "abcdef" + w_ustr = space.wrap(ustr.decode("ascii")) + result = api.PyUnicode_AsASCIIString(w_ustr) + + assert space.eq_w(space.wrap(ustr), result) + + w_ustr = space.wrap(u"abcd\xe9f") + result = api.PyUnicode_AsASCIIString(w_ustr) + assert result is None + + Modified: pypy/trunk/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/trunk/pypy/module/cpyext/unicodeobject.py Tue Jun 15 08:46:48 2010 @@ -307,6 +307,19 @@ w_errors = space.w_None return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors) + at cpython_api([PyObject], PyObject) +def PyUnicode_AsASCIIString(space, w_unicode): + """Encode a Unicode object using ASCII and return the result as Python string + object. Error handling is "strict". Return NULL if an exception was raised + by the codec.""" + try: + return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors? + except OperationError, e: + if e.match(space, space.w_UnicodeEncodeError): + return None + else: + raise + if sys.platform == 'win32': @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject) def PyUnicode_EncodeMBCS(space, wchar_p, length, errors): From antocuni at codespeak.net Tue Jun 15 11:33:59 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jun 2010 11:33:59 +0200 (CEST) Subject: [pypy-svn] r75404 - pypy/branch/sys-prefix/pypy/module/sys Message-ID: <20100615093359.5476C282BDA@codespeak.net> Author: antocuni Date: Tue Jun 15 11:33:57 2010 New Revision: 75404 Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py Log: actually set sys.{prefix, exec_prefix}. We need to think what to do with pypy_prefix, but I think it should be removed Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/state.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/state.py Tue Jun 15 11:33:57 2010 @@ -64,7 +64,11 @@ except OSError: return space.w_None else: - space.setitem(space.sys.w_dict, space.wrap('pypy_prefix'), + space.setitem(space.sys.w_dict, space.wrap('pypy_prefix'), # XXX remove me + space.wrap(srcdir)) + space.setitem(space.sys.w_dict, space.wrap('prefix'), + space.wrap(srcdir)) + space.setitem(space.sys.w_dict, space.wrap('exec_prefix'), space.wrap(srcdir)) return space.newlist([space.wrap(p) for p in path]) From afa at codespeak.net Tue Jun 15 16:34:00 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 15 Jun 2010 16:34:00 +0200 (CEST) Subject: [pypy-svn] r75405 - in pypy/trunk/pypy/translator: . c platform Message-ID: <20100615143400.03EF6282BDA@codespeak.net> Author: afa Date: Tue Jun 15 16:33:58 2010 New Revision: 75405 Modified: pypy/trunk/pypy/translator/c/genc.py pypy/trunk/pypy/translator/driver.py pypy/trunk/pypy/translator/platform/posix.py pypy/trunk/pypy/translator/platform/windows.py Log: Fix inconsistencies between the genc builder and the Makefile. now the --shared option works with or without a makefile, and also with the mingw32 compiler on Windows. The shared library is named consistently. for example: libpypy-c.dll for pypy-c.exe Modified: pypy/trunk/pypy/translator/c/genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/genc.py (original) +++ pypy/trunk/pypy/translator/c/genc.py Tue Jun 15 16:33:58 2010 @@ -227,7 +227,7 @@ funcgen.patch_graph(copy_graph=False) return db - def generate_source(self, db=None, defines={}): + def generate_source(self, db=None, defines={}, exe_name=None): assert self.c_source_filename is None translator = self.translator @@ -271,7 +271,7 @@ defines = defines) self.c_source_filename = py.path.local(cfile) self.extrafiles = self.eventually_copy(extra) - self.gen_makefile(targetdir) + self.gen_makefile(targetdir, exe_name=exe_name) return cfile def eventually_copy(self, cfiles): @@ -482,7 +482,7 @@ # build main program eci = self.get_eci() kw = {} - if self.translator.platform.so_ext == 'so': + if self.translator.platform.cc == 'gcc': kw['libraries'] = [self.shared_library_name.purebasename[3:]] kw['library_dirs'] = [self.targetdir] else: @@ -516,6 +516,10 @@ extra_opts += ['-j', str(self.config.translation.make_jobs)] self.translator.platform.execute_makefile(self.targetdir, extra_opts) + if shared: + self.shared_library_name = self.executable_name.new( + purebasename='lib' + self.executable_name.purebasename, + ext=self.translator.platform.so_ext) else: compiler = CCompilerDriver(self.translator.platform, [self.c_source_filename] + self.extrafiles, @@ -531,6 +535,8 @@ def gen_makefile(self, targetdir, exe_name=None): cfiles = [self.c_source_filename] + self.extrafiles + if exe_name is not None: + exe_name = targetdir.join(exe_name) mk = self.translator.platform.gen_makefile( cfiles, self.eci, path=targetdir, exe_name=exe_name, Modified: pypy/trunk/pypy/translator/driver.py ============================================================================== --- pypy/trunk/pypy/translator/driver.py (original) +++ pypy/trunk/pypy/translator/driver.py Tue Jun 15 16:33:58 2010 @@ -513,7 +513,12 @@ defines = cbuilder.DEBUG_DEFINES else: defines = {} - c_source_filename = cbuilder.generate_source(database, defines) + if self.exe_name is not None: + exe_name = self.exe_name % self.get_info() + else: + exe_name = None + c_source_filename = cbuilder.generate_source(database, defines, + exe_name=exe_name) self.log.info("written: %s" % (c_source_filename,)) if self.config.translation.dump_static_data_info: from pypy.translator.tool.staticsizereport import dump_static_data_info @@ -530,19 +535,20 @@ newexename = self.exe_name % self.get_info() if '/' not in newexename and '\\' not in newexename: newexename = './' + newexename - return mkexename(py.path.local(newexename)) + return py.path.local(newexename) def create_exe(self): """ Copy the compiled executable into translator/goal """ if self.exe_name is not None: - exename = mkexename(self.c_entryp) - newexename = self.compute_exe_name() + exename = self.c_entryp + newexename = mkexename(self.compute_exe_name()) shutil.copy(str(exename), str(newexename)) if self.cbuilder.shared_library_name is not None: soname = self.cbuilder.shared_library_name newsoname = newexename.new(basename=soname.basename) shutil.copy(str(soname), str(newsoname)) + self.log.info("copied: %s" % (newsoname,)) self.c_entryp = newexename self.log.info("created: %s" % (self.c_entryp,)) Modified: pypy/trunk/pypy/translator/platform/posix.py ============================================================================== --- pypy/trunk/pypy/translator/platform/posix.py (original) +++ pypy/trunk/pypy/translator/platform/posix.py Tue Jun 15 16:33:58 2010 @@ -83,6 +83,8 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) linkflags = self.link_flags[:] if shared: @@ -146,6 +148,7 @@ if shared: m.definition('SHARED_IMPORT_LIB', libname), + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo "' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Tue Jun 15 16:33:58 2010 @@ -208,6 +208,8 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) m = NMakefile(path) m.exe_name = exe_name @@ -220,7 +222,8 @@ linkflags += self._exportsymbols_link_flags(eci) if shared: - so_name = exe_name.new(ext=self.so_ext) + so_name = exe_name.new(purebasename='lib' + exe_name.purebasename, + ext=self.so_ext) target_name = so_name.basename else: target_name = exe_name.basename @@ -334,6 +337,7 @@ shared_only = [] cflags = ['-O3'] link_flags = [] + exe_ext = 'exe' so_ext = 'dll' def __init__(self, cc=None): From afa at codespeak.net Tue Jun 15 16:36:40 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 15 Jun 2010 16:36:40 +0200 (CEST) Subject: [pypy-svn] r75406 - pypy/trunk/pypy/tool/release Message-ID: <20100615143640.A60D0282BDA@codespeak.net> Author: afa Date: Tue Jun 15 16:36:39 2010 New Revision: 75406 Modified: pypy/trunk/pypy/tool/release/pack.py Log: Fix the script to follow the new dll naming convention Modified: pypy/trunk/pypy/tool/release/pack.py ============================================================================== --- pypy/trunk/pypy/tool/release/pack.py (original) +++ pypy/trunk/pypy/tool/release/pack.py Tue Jun 15 16:36:39 2010 @@ -10,7 +10,7 @@ def filenames_from_platform(platform): if platform == 'win32': files = [goal_dir / 'pypy-c.exe'] - dll = goal_dir.join('libpypy-c.exe.dll') + dll = goal_dir / 'libpypy-c.dll' if dll.check(): files.append(dll) else: From jcreigh at codespeak.net Tue Jun 15 18:00:30 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 15 Jun 2010 18:00:30 +0200 (CEST) Subject: [pypy-svn] r75407 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100615160030.3682E282B9D@codespeak.net> Author: jcreigh Date: Tue Jun 15 18:00:28 2010 New Revision: 75407 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Log: handle MOV_ji when both operands are 64-bit Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Tue Jun 15 18:00:28 2010 @@ -30,13 +30,11 @@ assert ebp_offset < 0 # so no confusion with RegLoc.value self.position = position self.value = ebp_offset - # XXX: Word size hardcoded self.width = num_words * WORD # One of INT, REF, FLOAT self.type = type def frame_size(self): - # XXX: word size return self.width // WORD def __repr__(self): @@ -55,7 +53,6 @@ assert regnum >= 0 self.value = regnum self.is_xmm = is_xmm - # XXX: Word size if self.is_xmm: self.width = 8 else: @@ -169,15 +166,24 @@ val1 = getattr(loc1, "value_" + possible_code1)() val2 = getattr(loc2, "value_" + possible_code2)() # XXX: Could use RIP+disp32 in some cases - if self.WORD == 8 and possible_code1 == 'j': + if self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2): + if possible_code1 == 'j': + # This is the worst case: MOV_ji, and both operands are 64-bit + # Hopefully this doesn't happen too often + self.PUSH_r(eax.value) + self.MOV_ri(eax.value, val1) + self.MOV_ri(X86_64_SCRATCH_REG.value, val2) + self.MOV_mr((eax.value, 0), X86_64_SCRATCH_REG.value) + self.POP_r(eax.value) + else: + self.MOV_ri(X86_64_SCRATCH_REG.value, val2) + getattr(self, name + "_" + possible_code1 + "r")(val1, X86_64_SCRATCH_REG.value) + elif self.WORD == 8 and possible_code1 == 'j': self.MOV_ri(X86_64_SCRATCH_REG.value, val1) getattr(self, name + "_" + "m" + possible_code2)((X86_64_SCRATCH_REG.value, 0), val2) elif self.WORD == 8 and possible_code2 == 'j': self.MOV_ri(X86_64_SCRATCH_REG.value, val2) getattr(self, name + "_" + possible_code1 + "m")(val1, (X86_64_SCRATCH_REG.value, 0)) - elif self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2): - self.MOV_ri(X86_64_SCRATCH_REG.value, val2) - getattr(self, name + "_" + possible_code1 + "r")(val1, X86_64_SCRATCH_REG.value) else: methname = name + "_" + possible_code1 + possible_code2 getattr(self, methname)(val1, val2) From afa at codespeak.net Tue Jun 15 18:04:21 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 15 Jun 2010 18:04:21 +0200 (CEST) Subject: [pypy-svn] r75408 - in pypy/trunk/pypy: module/cpyext/include tool Message-ID: <20100615160421.1C447282B9D@codespeak.net> Author: afa Date: Tue Jun 15 18:04:20 2010 New Revision: 75408 Modified: pypy/trunk/pypy/module/cpyext/include/Python.h pypy/trunk/pypy/tool/gcc_cache.py Log: - Import the "platform" on every compilation attempt: an option may have changed the compiler - fix cpyext when compiled with --cc=mingw32. Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Tue Jun 15 18:04:20 2010 @@ -15,7 +15,9 @@ #else # define MS_WIN32 1 # define MS_WINDOWS 1 -# include +# ifdef _MSC_VER +# include +# endif # include # define Py_DEPRECATED(VERSION_UNUSED) # ifdef Py_BUILD_CORE Modified: pypy/trunk/pypy/tool/gcc_cache.py ============================================================================== --- pypy/trunk/pypy/tool/gcc_cache.py (original) +++ pypy/trunk/pypy/tool/gcc_cache.py Tue Jun 15 18:04:20 2010 @@ -1,6 +1,5 @@ - from pypy.tool.autopath import pypydir -from pypy.translator.platform import platform, CompilationError +from pypy.translator.platform import CompilationError from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.compat import md5 import py @@ -8,6 +7,9 @@ cache_dir_root = py.path.local(pypydir).join('_cache').ensure(dir=1) def cache_file_path(c_files, eci, cachename): + "Builds a filename to cache compilation data" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform cache_dir = cache_dir_root.join(cachename).ensure(dir=1) filecontents = [c_file.read() for c_file in c_files] key = repr((filecontents, eci, platform.key())) @@ -15,6 +17,9 @@ return cache_dir.join(hash) def build_executable_cache(c_files, eci): + "Builds and run a program; caches the result" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'build_executable_cache') try: return path.read() @@ -24,6 +29,9 @@ return result.out def try_compile_cache(c_files, eci): + "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() From fijal at codespeak.net Tue Jun 15 19:05:35 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 15 Jun 2010 19:05:35 +0200 (CEST) Subject: [pypy-svn] r75409 - in pypy/release/1.3.x: . pypy/tool/release pypy/translator pypy/translator/c pypy/translator/platform Message-ID: <20100615170535.C3C1B282B9D@codespeak.net> Author: fijal Date: Tue Jun 15 19:05:33 2010 New Revision: 75409 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/tool/release/pack.py pypy/release/1.3.x/pypy/translator/c/genc.py pypy/release/1.3.x/pypy/translator/driver.py pypy/release/1.3.x/pypy/translator/platform/posix.py pypy/release/1.3.x/pypy/translator/platform/windows.py Log: Merge 75405 and 75406 from trunk Modified: pypy/release/1.3.x/pypy/tool/release/pack.py ============================================================================== --- pypy/release/1.3.x/pypy/tool/release/pack.py (original) +++ pypy/release/1.3.x/pypy/tool/release/pack.py Tue Jun 15 19:05:33 2010 @@ -10,7 +10,7 @@ def filenames_from_platform(platform): if platform == 'win32': files = [goal_dir / 'pypy-c.exe'] - dll = goal_dir.join('libpypy-c.exe.dll') + dll = goal_dir / 'libpypy-c.dll' if dll.check(): files.append(dll) else: Modified: pypy/release/1.3.x/pypy/translator/c/genc.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/c/genc.py (original) +++ pypy/release/1.3.x/pypy/translator/c/genc.py Tue Jun 15 19:05:33 2010 @@ -227,7 +227,7 @@ funcgen.patch_graph(copy_graph=False) return db - def generate_source(self, db=None, defines={}): + def generate_source(self, db=None, defines={}, exe_name=None): assert self.c_source_filename is None translator = self.translator @@ -271,7 +271,7 @@ defines = defines) self.c_source_filename = py.path.local(cfile) self.extrafiles = self.eventually_copy(extra) - self.gen_makefile(targetdir) + self.gen_makefile(targetdir, exe_name=exe_name) return cfile def eventually_copy(self, cfiles): @@ -482,7 +482,7 @@ # build main program eci = self.get_eci() kw = {} - if self.translator.platform.so_ext == 'so': + if self.translator.platform.cc == 'gcc': kw['libraries'] = [self.shared_library_name.purebasename[3:]] kw['library_dirs'] = [self.targetdir] else: @@ -516,6 +516,10 @@ extra_opts += ['-j', str(self.config.translation.make_jobs)] self.translator.platform.execute_makefile(self.targetdir, extra_opts) + if shared: + self.shared_library_name = self.executable_name.new( + purebasename='lib' + self.executable_name.purebasename, + ext=self.translator.platform.so_ext) else: compiler = CCompilerDriver(self.translator.platform, [self.c_source_filename] + self.extrafiles, @@ -531,6 +535,8 @@ def gen_makefile(self, targetdir, exe_name=None): cfiles = [self.c_source_filename] + self.extrafiles + if exe_name is not None: + exe_name = targetdir.join(exe_name) mk = self.translator.platform.gen_makefile( cfiles, self.eci, path=targetdir, exe_name=exe_name, Modified: pypy/release/1.3.x/pypy/translator/driver.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/driver.py (original) +++ pypy/release/1.3.x/pypy/translator/driver.py Tue Jun 15 19:05:33 2010 @@ -513,7 +513,12 @@ defines = cbuilder.DEBUG_DEFINES else: defines = {} - c_source_filename = cbuilder.generate_source(database, defines) + if self.exe_name is not None: + exe_name = self.exe_name % self.get_info() + else: + exe_name = None + c_source_filename = cbuilder.generate_source(database, defines, + exe_name=exe_name) self.log.info("written: %s" % (c_source_filename,)) if self.config.translation.dump_static_data_info: from pypy.translator.tool.staticsizereport import dump_static_data_info @@ -530,19 +535,20 @@ newexename = self.exe_name % self.get_info() if '/' not in newexename and '\\' not in newexename: newexename = './' + newexename - return mkexename(py.path.local(newexename)) + return py.path.local(newexename) def create_exe(self): """ Copy the compiled executable into translator/goal """ if self.exe_name is not None: - exename = mkexename(self.c_entryp) - newexename = self.compute_exe_name() + exename = self.c_entryp + newexename = mkexename(self.compute_exe_name()) shutil.copy(str(exename), str(newexename)) if self.cbuilder.shared_library_name is not None: soname = self.cbuilder.shared_library_name newsoname = newexename.new(basename=soname.basename) shutil.copy(str(soname), str(newsoname)) + self.log.info("copied: %s" % (newsoname,)) self.c_entryp = newexename self.log.info("created: %s" % (self.c_entryp,)) Modified: pypy/release/1.3.x/pypy/translator/platform/posix.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/posix.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/posix.py Tue Jun 15 19:05:33 2010 @@ -83,6 +83,8 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) linkflags = self.link_flags[:] if shared: @@ -146,6 +148,7 @@ if shared: m.definition('SHARED_IMPORT_LIB', libname), + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo "' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' Modified: pypy/release/1.3.x/pypy/translator/platform/windows.py ============================================================================== --- pypy/release/1.3.x/pypy/translator/platform/windows.py (original) +++ pypy/release/1.3.x/pypy/translator/platform/windows.py Tue Jun 15 19:05:33 2010 @@ -208,6 +208,8 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) m = NMakefile(path) m.exe_name = exe_name @@ -220,7 +222,8 @@ linkflags += self._exportsymbols_link_flags(eci) if shared: - so_name = exe_name.new(ext=self.so_ext) + so_name = exe_name.new(purebasename='lib' + exe_name.purebasename, + ext=self.so_ext) target_name = so_name.basename else: target_name = exe_name.basename @@ -334,6 +337,7 @@ shared_only = [] cflags = ['-O3'] link_flags = [] + exe_ext = 'exe' so_ext = 'dll' def __init__(self, cc=None): From arigo at codespeak.net Tue Jun 15 19:37:37 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jun 2010 19:37:37 +0200 (CEST) Subject: [pypy-svn] r75410 - in pypy/trunk/pypy: annotation annotation/test rpython rpython/lltypesystem rpython/ootypesystem rpython/test Message-ID: <20100615173737.BF94F282B9D@codespeak.net> Author: arigo Date: Tue Jun 15 19:37:35 2010 New Revision: 75410 Modified: pypy/trunk/pypy/annotation/builtin.py pypy/trunk/pypy/annotation/test/test_annrpython.py pypy/trunk/pypy/annotation/unaryop.py pypy/trunk/pypy/rpython/lltypesystem/rlist.py pypy/trunk/pypy/rpython/ootypesystem/rlist.py pypy/trunk/pypy/rpython/rbuiltin.py pypy/trunk/pypy/rpython/rmodel.py pypy/trunk/pypy/rpython/rrange.py pypy/trunk/pypy/rpython/test/test_rrange.py Log: Experimental: enumerate() support in RPython, at least on lists. Modified: pypy/trunk/pypy/annotation/builtin.py ============================================================================== --- pypy/trunk/pypy/annotation/builtin.py (original) +++ pypy/trunk/pypy/annotation/builtin.py Tue Jun 15 19:37:35 2010 @@ -8,7 +8,7 @@ from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString from pypy.annotation.model import SomePBC, SomeInstance, SomeDict, SomeList -from pypy.annotation.model import SomeWeakRef +from pypy.annotation.model import SomeWeakRef, SomeIterator from pypy.annotation.model import SomeOOObject from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation from pypy.annotation.model import add_knowntypedata @@ -85,6 +85,9 @@ builtin_xrange = builtin_range # xxx for now allow it +def builtin_enumerate(s_obj): + return SomeIterator(s_obj, "enumerate") + def builtin_bool(s_obj): return s_obj.is_true() Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Tue Jun 15 19:37:35 2010 @@ -3332,6 +3332,16 @@ a = self.RPythonAnnotator() py.test.raises(AssertionError, a.build_types, f, []) + def test_enumerate(self): + def f(): + for i, x in enumerate(['a', 'b', 'c', 'd']): + if i == 2: + return x + return '?' + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeChar) + def g(n): return [0,1,2,n] Modified: pypy/trunk/pypy/annotation/unaryop.py ============================================================================== --- pypy/trunk/pypy/annotation/unaryop.py (original) +++ pypy/trunk/pypy/annotation/unaryop.py Tue Jun 15 19:37:35 2010 @@ -577,6 +577,9 @@ return can_throw def next(itr): + if itr.variant == ("enumerate",): + s_item = itr.s_container.getanyitem() + return SomeTuple((SomeInteger(nonneg=True), s_item)) return itr.s_container.getanyitem(*itr.variant) next.can_only_throw = _can_only_throw method_next = next Modified: pypy/trunk/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rlist.py Tue Jun 15 19:37:35 2010 @@ -388,6 +388,7 @@ ('index', Signed))) self.ll_listiter = ll_listiter self.ll_listnext = ll_listnext + self.ll_getnextindex = ll_getnextindex def ll_listiter(ITERPTR, lst): iter = malloc(ITERPTR.TO) @@ -402,3 +403,6 @@ raise StopIteration iter.index = index + 1 # cannot overflow because index < l.length return l.ll_getitem_fast(index) + +def ll_getnextindex(iter): + return iter.index Modified: pypy/trunk/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/rlist.py Tue Jun 15 19:37:35 2010 @@ -245,6 +245,7 @@ {"iterable": r_list.lowleveltype, "index": ootype.Signed}) self.ll_listiter = ll_listiter self.ll_listnext = ll_listnext + self.ll_getnextindex = ll_getnextindex def ll_listiter(ITER, lst): @@ -261,3 +262,5 @@ iter.index = index + 1 return l.ll_getitem_fast(index) +def ll_getnextindex(iter): + return iter.index Modified: pypy/trunk/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/trunk/pypy/rpython/rbuiltin.py (original) +++ pypy/trunk/pypy/rpython/rbuiltin.py Tue Jun 15 19:37:35 2010 @@ -7,6 +7,7 @@ from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange +from pypy.rpython.rrange import rtype_builtin_enumerate from pypy.rpython import rstr from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr @@ -229,6 +230,8 @@ #def rtype_builtin_xrange(hop): see rrange.py +#def rtype_builtin_enumerate(hop): see rrange.py + #def rtype_r_dict(hop): see rdict.py def rtype_intmask(hop): Modified: pypy/trunk/pypy/rpython/rmodel.py ============================================================================== --- pypy/trunk/pypy/rpython/rmodel.py (original) +++ pypy/trunk/pypy/rpython/rmodel.py Tue Jun 15 19:37:35 2010 @@ -268,6 +268,10 @@ # NOTE: SomeIterator is for iterators over any container, not just list def rtyper_makerepr(self, rtyper): r_container = rtyper.getrepr(self.s_container) + if self.variant == ("enumerate",): + from pypy.rpython.rrange import EnumerateIteratorRepr + r_baseiter = r_container.make_iterator_repr() + return EnumerateIteratorRepr(r_baseiter) return r_container.make_iterator_repr(*self.variant) def rtyper_makekey_ex(self, rtyper): return self.__class__, rtyper.makekey(self.s_container), self.variant Modified: pypy/trunk/pypy/rpython/rrange.py ============================================================================== --- pypy/trunk/pypy/rpython/rrange.py (original) +++ pypy/trunk/pypy/rpython/rrange.py Tue Jun 15 19:37:35 2010 @@ -185,3 +185,28 @@ return ll_rangenext_up(iter, step) else: return ll_rangenext_down(iter, step) + +# ____________________________________________________________ +# +# Support for enumerate(). + +class EnumerateIteratorRepr(IteratorRepr): + def __init__(self, r_baseiter): + self.r_baseiter = r_baseiter + self.lowleveltype = r_baseiter.lowleveltype + # only supports for now enumerate() on sequence types whose iterators + # have a method ll_getnextindex. It's easy to add one for most + # iterator types, but I didn't do it so far. + self.ll_getnextindex = r_baseiter.ll_getnextindex + + def rtype_next(self, hop): + v_enumerate, = hop.inputargs(self) + v_index = hop.gendirectcall(self.ll_getnextindex, v_enumerate) + hop2 = hop.copy() + hop2.args_r = [self.r_baseiter] + v_item = self.r_baseiter.rtype_next(hop2) + return hop.r_result.newtuple(hop.llops, hop.r_result, + [v_index, v_item]) + +def rtype_builtin_enumerate(hop): + return hop.r_result.r_baseiter.newiter(hop) Modified: pypy/trunk/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rrange.py (original) +++ pypy/trunk/pypy/rpython/test/test_rrange.py Tue Jun 15 19:37:35 2010 @@ -160,6 +160,15 @@ res = self.interpret(fn, []) assert res == 0 + def test_enumerate(self): + def fn(n): + for i, x in enumerate([123, 456, 789, 654]): + if i == n: + return x + return 5 + res = self.interpret(fn, [2]) + assert res == 789 + class TestLLtype(BaseTestRrange, LLRtypeMixin): from pypy.rpython.lltypesystem import rrange From arigo at codespeak.net Tue Jun 15 20:47:31 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jun 2010 20:47:31 +0200 (CEST) Subject: [pypy-svn] r75413 - pypy/trunk/pypy/doc Message-ID: <20100615184731.D8BBD282B9D@codespeak.net> Author: arigo Date: Tue Jun 15 20:47:29 2010 New Revision: 75413 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Minor stuff. Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Tue Jun 15 20:47:29 2010 @@ -8,16 +8,17 @@ points. First of all, we stabilized the JIT compiler since 1.2 release, answered user issues, fixed bugs and generally improved speed. -On the other hand, we're pleased to announce alpha support for loading +The other point is that we're pleased to announce alpha support for loading CPython extension modules written in C. While the main point of the release -is increased stability, this part is in alpha stage and it is not yet suited +is increased stability, this part is in alpha stage and it is not yet suited for production environments. Highlight of this release ========================= XXX a rough list -- cpyext +- cpyext (some details, in particular: the extension module must be + recompiled, and typically "bug-fixed" w.r.t. refcounting) - bugfixes - blackhole-improvements - minor jit improvements From arigo at codespeak.net Tue Jun 15 21:00:27 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jun 2010 21:00:27 +0200 (CEST) Subject: [pypy-svn] r75414 - in pypy/trunk/pypy/jit/codewriter: . test Message-ID: <20100615190027.4E9B8282B9D@codespeak.net> Author: arigo Date: Tue Jun 15 21:00:25 2010 New Revision: 75414 Modified: pypy/trunk/pypy/jit/codewriter/flatten.py pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Log: Generate last_exception and last_exc_value always in the same order, to help the test. Modified: pypy/trunk/pypy/jit/codewriter/flatten.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/flatten.py (original) +++ pypy/trunk/pypy/jit/codewriter/flatten.py Tue Jun 15 21:00:25 2010 @@ -325,9 +325,12 @@ # Write 'last_exc_xxx' operations that load the last exception # directly into the locations specified by 'inputargs'. This # must be done at the end of the link renamings. + if link.last_exception is link.last_exc_value is None: + return for v, w in zip(link.args, inputargs): if v is link.last_exception: self.emitline("last_exception", "->", self.getcolor(w)) + for v, w in zip(link.args, inputargs): if v is link.last_exc_value: self.emitline("last_exc_value", "->", self.getcolor(w)) Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Tue Jun 15 21:00:25 2010 @@ -430,8 +430,8 @@ void_return --- L1: - last_exc_value -> %r0 last_exception -> %i1 + last_exc_value -> %r0 setfield_gc_i $<* struct test.Foo>, , $5 -live- raise %r0 From fijal at codespeak.net Wed Jun 16 01:17:47 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jun 2010 01:17:47 +0200 (CEST) Subject: [pypy-svn] r75415 - in pypy/release/1.3.x: . pypy/jit/codewriter pypy/jit/codewriter/test Message-ID: <20100615231747.0FF58282B9D@codespeak.net> Author: fijal Date: Wed Jun 16 01:17:46 2010 New Revision: 75415 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/jit/codewriter/flatten.py pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py Log: Merge 75414 from trunk, should fix 64bit tests Modified: pypy/release/1.3.x/pypy/jit/codewriter/flatten.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/flatten.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/flatten.py Wed Jun 16 01:17:46 2010 @@ -325,9 +325,12 @@ # Write 'last_exc_xxx' operations that load the last exception # directly into the locations specified by 'inputargs'. This # must be done at the end of the link renamings. + if link.last_exception is link.last_exc_value is None: + return for v, w in zip(link.args, inputargs): if v is link.last_exception: self.emitline("last_exception", "->", self.getcolor(w)) + for v, w in zip(link.args, inputargs): if v is link.last_exc_value: self.emitline("last_exc_value", "->", self.getcolor(w)) Modified: pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/release/1.3.x/pypy/jit/codewriter/test/test_flatten.py Wed Jun 16 01:17:46 2010 @@ -430,8 +430,8 @@ void_return --- L1: - last_exc_value -> %r0 last_exception -> %i1 + last_exc_value -> %r0 setfield_gc_i $<* struct test.Foo>, , $5 -live- raise %r0 From fijal at codespeak.net Wed Jun 16 02:11:02 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jun 2010 02:11:02 +0200 (CEST) Subject: [pypy-svn] r75416 - in pypy/trunk/pypy/tool: . release release/test test Message-ID: <20100616001102.D527A282B9D@codespeak.net> Author: fijal Date: Wed Jun 16 02:11:01 2010 New Revision: 75416 Added: pypy/trunk/pypy/tool/release/package.py - copied unchanged from r75351, pypy/trunk/pypy/tool/package.py pypy/trunk/pypy/tool/release/test/test_package.py - copied, changed from r75351, pypy/trunk/pypy/tool/test/test_package.py Removed: pypy/trunk/pypy/tool/package.py pypy/trunk/pypy/tool/test/test_package.py Log: Move package into release Copied: pypy/trunk/pypy/tool/release/test/test_package.py (from r75351, pypy/trunk/pypy/tool/test/test_package.py) ============================================================================== --- pypy/trunk/pypy/tool/test/test_package.py (original) +++ pypy/trunk/pypy/tool/release/test/test_package.py Wed Jun 16 02:11:01 2010 @@ -1,7 +1,7 @@ import py from pypy.tool.autopath import pypydir -from pypy.tool.package import main +from pypy.tool.release.package import main import tarfile, os def test_dir_structure(): From fijal at codespeak.net Wed Jun 16 05:18:40 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jun 2010 05:18:40 +0200 (CEST) Subject: [pypy-svn] r75417 - in pypy/trunk/pypy/tool/release: . test Message-ID: <20100616031840.18D29282B9D@codespeak.net> Author: fijal Date: Wed Jun 16 05:18:39 2010 New Revision: 75417 Modified: pypy/trunk/pypy/tool/release/make_release.py pypy/trunk/pypy/tool/release/package.py pypy/trunk/pypy/tool/release/test/test_package.py Log: Finish writing a tool that'll package pypy-c's out of nightly builds Modified: pypy/trunk/pypy/tool/release/make_release.py ============================================================================== --- pypy/trunk/pypy/tool/release/make_release.py (original) +++ pypy/trunk/pypy/tool/release/make_release.py Wed Jun 16 05:18:39 2010 @@ -7,13 +7,20 @@ Usage: make_release.py release/ """ +import autopath import sys import urllib2 from xml.dom import minidom import re +import py +from pypy.tool.udir import udir +from pypy.tool.release.package import package +import tarfile + +BASEURL = 'http://buildbot.pypy.org/nightly/' def browse_nightly(branch, - baseurl='http://buildbot.pypy.org/nightly/', + baseurl=BASEURL, override_xml=None): if override_xml is None: url = baseurl + branch + '/' @@ -36,13 +43,36 @@ d[(kind, platform)] = rev, ref return d -def main(branch): +def main(branch, release): to_download = browse_nightly(branch) - xxx # finish me + tmpdir = udir.join('download') + tmpdir.ensure(dir=True) + for (kind, platform), (rev, name) in to_download.iteritems(): + if platform == 'win32': + print 'Ignoring %s, windows unsupported' % name + else: + print "Downloading %s at rev %d" % (name, rev) + url = BASEURL + branch + "/" + name + data = urllib2.urlopen(url).read() + tmpdir.join(name).write(data, mode="wb") + t = tarfile.open(str(tmpdir.join(name))) + data = t.extractfile('pypy-c').read() + pypy_c = tmpdir.join('pypy-c') + pypy_c.write(data, mode="wb") + if kind == 'jit': + kind = '' + else: + kind = '-' + kind + name = 'pypy-%s%s-%s' % (release, kind, platform) + builddir = package(py.path.local(autopath.pypydir).join('..'), + name=name, + override_pypy_c=pypy_c) + print "Build %s/%s.tar.bz2" % (builddir, name) + print "\nLook into %s for packages" % builddir if __name__ == '__main__': if len(sys.argv) != 2: print __doc__ sys.exit(1) - main(sys.argv[1]) + main(sys.argv[1], release='1.3') Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Wed Jun 16 05:18:39 2010 @@ -31,9 +31,13 @@ class PyPyCNotFound(Exception): pass -def main(basedir, name='pypy-nightly', rename_pypy_c='pypy-c'): +def package(basedir, name='pypy-nightly', rename_pypy_c='pypy-c', + override_pypy_c = None): basedir = py.path.local(basedir) - pypy_c = basedir.join('pypy', 'translator', 'goal', 'pypy-c') + if override_pypy_c is None: + pypy_c = basedir.join('pypy', 'translator', 'goal', 'pypy-c') + else: + pypy_c = py.path.local(override_pypy_c) if not pypy_c.check(): raise PyPyCNotFound('Please compile pypy first, using translate.py') builddir = udir.ensure("build", dir=True) @@ -67,4 +71,4 @@ print >>sys.stderr, __doc__ sys.exit(1) else: - main(*sys.argv[1:]) + package(*sys.argv[1:]) Modified: pypy/trunk/pypy/tool/release/test/test_package.py ============================================================================== --- pypy/trunk/pypy/tool/release/test/test_package.py (original) +++ pypy/trunk/pypy/tool/release/test/test_package.py Wed Jun 16 05:18:39 2010 @@ -1,7 +1,7 @@ import py from pypy.tool.autopath import pypydir -from pypy.tool.release.package import main +from pypy.tool.release.package import package import tarfile, os def test_dir_structure(): @@ -13,7 +13,7 @@ else: fake_pypy_c = False try: - builddir = main(py.path.local(pypydir).dirpath(), 'test') + builddir = package(py.path.local(pypydir).dirpath(), 'test') assert builddir.join('test', 'lib-python', '2.5.2', 'test').check() assert builddir.join('test', 'bin', 'pypy-c').check() assert builddir.join('test', 'pypy', 'lib', 'syslog.py').check() From fijal at codespeak.net Wed Jun 16 08:24:47 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jun 2010 08:24:47 +0200 (CEST) Subject: [pypy-svn] r75418 - pypy/trunk/py/_process Message-ID: <20100616062447.0F7DF282B9D@codespeak.net> Author: fijal Date: Wed Jun 16 08:24:46 2010 New Revision: 75418 Modified: pypy/trunk/py/_process/cmdexec.py Log: This seems to fix some of 64bit issues. A bit "what the hell", but makes some sort of sense. Modified: pypy/trunk/py/_process/cmdexec.py ============================================================================== --- pypy/trunk/py/_process/cmdexec.py (original) +++ pypy/trunk/py/_process/cmdexec.py Wed Jun 16 08:24:46 2010 @@ -18,8 +18,8 @@ universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.getdefaultencoding()) - err = py.builtin._totext(err, sys.getdefaultencoding()) + out = py.builtin._totext(out, sys.stdout.encoding) + err = py.builtin._totext(err, sys.stderr.encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) From afa at codespeak.net Wed Jun 16 11:00:29 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 16 Jun 2010 11:00:29 +0200 (CEST) Subject: [pypy-svn] r75419 - pypy/trunk/pypy/translator Message-ID: <20100616090029.BD606282B9D@codespeak.net> Author: afa Date: Wed Jun 16 11:00:27 2010 New Revision: 75419 Modified: pypy/trunk/pypy/translator/translator.py Log: Don't import the FlowObjSpace too early: among its dependencies is the rffi module, which needs the compiler to define its types. This causes problems when using the --cc option. (the change that broke --cc is r73857, in pyframe.py; but it feels more robust to defer the import in translator.py) Modified: pypy/trunk/pypy/translator/translator.py ============================================================================== --- pypy/trunk/pypy/translator/translator.py (original) +++ pypy/trunk/pypy/translator/translator.py Wed Jun 16 11:00:27 2010 @@ -7,7 +7,6 @@ import autopath, os, sys, types, copy from pypy.translator import simplify -from pypy.objspace.flow.objspace import FlowObjSpace from pypy.objspace.flow.model import FunctionGraph, checkgraph, Block from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func @@ -67,6 +66,7 @@ else: if self.config.translation.verbose: log.start(nice_repr_for_func(func)) + from pypy.objspace.flow.objspace import FlowObjSpace space = FlowObjSpace(self.flowconfig) if self.annotator: # ZZZ From afa at codespeak.net Wed Jun 16 11:31:01 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 16 Jun 2010 11:31:01 +0200 (CEST) Subject: [pypy-svn] r75420 - pypy/trunk/pypy/translator/goal Message-ID: <20100616093101.D42CF282B9D@codespeak.net> Author: afa Date: Wed Jun 16 11:31:00 2010 New Revision: 75420 Modified: pypy/trunk/pypy/translator/goal/targetpreimportedpypy.py pypy/trunk/pypy/translator/goal/targetpypystandalone.py Log: Remove unneeded import, and really fix --cc= Modified: pypy/trunk/pypy/translator/goal/targetpreimportedpypy.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetpreimportedpypy.py (original) +++ pypy/trunk/pypy/translator/goal/targetpreimportedpypy.py Wed Jun 16 11:31:00 2010 @@ -3,7 +3,6 @@ import os, sys sys.setrecursionlimit(17000) -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/trunk/pypy/translator/goal/targetpypystandalone.py Wed Jun 16 11:31:00 2010 @@ -2,7 +2,6 @@ import os, sys -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy From antocuni at codespeak.net Wed Jun 16 14:45:29 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jun 2010 14:45:29 +0200 (CEST) Subject: [pypy-svn] r75421 - in pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils: . command Message-ID: <20100616124529.AD575282B9D@codespeak.net> Author: antocuni Date: Wed Jun 16 14:45:28 2010 New Revision: 75421 Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/cmd.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Log: move the default location of site-packages to $PREFIX/lib/pypy1.2/site-packages, instead of $PREFIX/site-packages Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/cmd.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/cmd.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/cmd.py Wed Jun 16 14:45:28 2010 @@ -18,7 +18,8 @@ # return a list of 'site' dirs for easy_install from pkg_resources import normalize_path sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep)) - sitedirs.append(os.path.join(sys.pypy_prefix, 'site-packages')) + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedirs.append(os.path.join(sys.prefix, 'lib', pypylib, 'site-packages')) sitedirs = map(normalize_path, sitedirs) return sitedirs Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py Wed Jun 16 14:45:28 2010 @@ -67,8 +67,8 @@ 'data' : '$base', }, 'pypy': { - 'purelib': '$base/site-packages', - 'platlib': '$base/site-packages', + 'purelib': '$base/lib/pypy$pypy_version_short/site-packages', + 'platlib': '$base/lib/pypy$pypy_version_short/site-packages', 'headers': '$base/include', 'scripts': '$base/bin', 'data' : '$base', @@ -283,6 +283,7 @@ 'dist_fullname': self.distribution.get_fullname(), 'py_version': py_version, 'py_version_short': py_version[0:3], + 'pypy_version_short': '%d.%d' % sys.pypy_version_info[:2], 'sys_prefix': prefix, 'prefix': prefix, 'sys_exec_prefix': exec_prefix, Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Wed Jun 16 14:45:28 2010 @@ -44,7 +44,8 @@ "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: prefix = PYPY_PREFIX - return os.path.join(prefix, "site-packages") + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + return os.path.join(prefix, 'lib', pypylib, 'site-packages') _config_vars = None From afa at codespeak.net Wed Jun 16 15:37:03 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 16 Jun 2010 15:37:03 +0200 (CEST) Subject: [pypy-svn] r75422 - in pypy/trunk/pypy/module/cpyext: . include test Message-ID: <20100616133703.B7874282B90@codespeak.net> Author: afa Date: Wed Jun 16 15:37:02 2010 New Revision: 75422 Modified: pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/cdatetime.py pypy/trunk/pypy/module/cpyext/include/datetime.h pypy/trunk/pypy/module/cpyext/state.py pypy/trunk/pypy/module/cpyext/test/test_cpyext.py pypy/trunk/pypy/module/cpyext/test/test_datetime.py Log: Avoid to prebuild the PyDateTimeAPI structure: this made pypy-c freeze the datetime and time modules. I'm sure this is not right, specially concerning the call to tzset(), and this does not work with --cc=mingw32. Now the PyDateTimeAPI pointer is filled only after the first call to PyDateTime_IMPORT; Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Wed Jun 16 15:37:02 2010 @@ -315,7 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), - 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.cdatetime.build_datetime_api(space)'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'None'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -617,7 +617,7 @@ if "#" in name: continue if typ == 'PyDateTime_CAPI*': - global_objects.append('%s _%s;' % (typ, name)) + continue elif name.startswith('PyExc_'): global_objects.append('%s _%s;' % (typ[:-1], name)) else: @@ -817,8 +817,7 @@ structs.append('extern PyTypeObject _%s;' % (name,)) structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) elif typ == 'PyDateTime_CAPI*': - structs.append('extern %s _%s;' % (typ[:-1], name)) - structs.append('%s %s = &_%s;' % (typ, name, name)) + structs.append('%s %s = NULL;' % (typ, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -871,8 +870,7 @@ if typ in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': - struct_ptr = w_obj - name = '_' + name + continue else: assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj Modified: pypy/trunk/pypy/module/cpyext/cdatetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/cdatetime.py (original) +++ pypy/trunk/pypy/module/cpyext/cdatetime.py Wed Jun 16 15:37:02 2010 @@ -1,9 +1,11 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import PyObject, make_ref +from pypy.rlib.objectmodel import we_are_translated +from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import from pypy.module.cpyext.typeobject import PyTypeObjectPtr +from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_renamer @@ -17,10 +19,16 @@ ('DeltaType', PyTypeObjectPtr), )) -def build_datetime_api(space): - w_datetime = PyImport_Import(space, space.wrap("datetime")) + at cpython_api([], lltype.Ptr(PyDateTime_CAPI), + error=lltype.nullptr(PyDateTime_CAPI)) +def _PyDateTime_Import(space): datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw') + if not we_are_translated(): + datetimeAPI_dealloc(space) + space.fromcache(State).datetimeAPI = datetimeAPI + + w_datetime = PyImport_Import(space, space.wrap("datetime")) w_type = space.getattr(w_datetime, space.wrap("date")) datetimeAPI.c_DateType = rffi.cast( PyTypeObjectPtr, make_ref(space, w_type)) @@ -36,9 +44,19 @@ return datetimeAPI - at cpython_api([], PyObject) -def _PyDateTime_Import(space): - return +def datetimeAPI_dealloc(space): + "Used in tests only, to please the refcount checker" + if we_are_translated(): + return + datetimeAPI = space.fromcache(State).datetimeAPI + if datetimeAPI is None: + return + space.fromcache(State).datetimeAPI = None + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateTimeType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_TimeType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DeltaType)) + lltype.free(datetimeAPI, flavor='raw') PyDateTime_Date = PyObject PyDateTime_Time = PyObject Modified: pypy/trunk/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/datetime.h (original) +++ pypy/trunk/pypy/module/cpyext/include/datetime.h Wed Jun 16 15:37:02 2010 @@ -14,7 +14,11 @@ } PyDateTime_CAPI; PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; -#define PyDateTime_IMPORT _PyDateTime_Import() +#define PyDateTime_IMPORT \ + do { \ + if(PyDateTimeAPI==NULL) \ + PyDateTimeAPI = _PyDateTime_Import(); \ + } while (0) typedef struct { PyObject_HEAD Modified: pypy/trunk/pypy/module/cpyext/state.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/state.py (original) +++ pypy/trunk/pypy/module/cpyext/state.py Wed Jun 16 15:37:02 2010 @@ -5,6 +5,8 @@ class State: + datetimeAPI = None # used in tests + def __init__(self, space): self.space = space self.reset() Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Wed Jun 16 15:37:02 2010 @@ -271,6 +271,8 @@ Py_DecRef(self.space, w_obj) state.non_heaptypes_w[:] = [] state.reset_borrowed_references() + from pypy.module.cpyext import cdatetime + cdatetime.datetimeAPI_dealloc(self.space) if self.check_and_print_leaks(): assert False, "Test leaks or loses object(s)." Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py Wed Jun 16 15:37:02 2010 @@ -85,6 +85,7 @@ module = self.import_extension('foo', [ ("get_types", "METH_NOARGS", """ + PyDateTime_IMPORT; return PyTuple_Pack(4, PyDateTimeAPI->DateType, PyDateTimeAPI->DateTimeType, From antocuni at codespeak.net Wed Jun 16 15:56:09 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jun 2010 15:56:09 +0200 (CEST) Subject: [pypy-svn] r75423 - in pypy/branch/sys-prefix/lib/pypy1.2: lib-python/modified-2.5.2 site-packages Message-ID: <20100616135609.9171C282B90@codespeak.net> Author: antocuni Date: Wed Jun 16 15:56:08 2010 New Revision: 75423 Added: pypy/branch/sys-prefix/lib/pypy1.2/site-packages/ pypy/branch/sys-prefix/lib/pypy1.2/site-packages/README - copied unchanged from r75402, pypy/branch/sys-prefix/lib/pypy1.2/lib-python/2.5.2/site-packages/README Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/site.py Log: make site.py finding the correct site-package directory, and also create one in the svn checkout Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/site.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/site.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/site.py Wed Jun 16 15:56:08 2010 @@ -175,8 +175,9 @@ def addsitepackages(known_paths): """Add site-packages to sys.path, in a PyPy-specific way.""" - if hasattr(sys, 'pypy_prefix'): - sitedir = os.path.join(sys.pypy_prefix, "site-packages") + if hasattr(sys, 'pypy_version_info'): + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedir = os.path.join(sys.prefix, 'lib', pypylib, 'site-packages') if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) return None From antocuni at codespeak.net Wed Jun 16 16:30:52 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jun 2010 16:30:52 +0200 (CEST) Subject: [pypy-svn] r75424 - pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils Message-ID: <20100616143052.3F0AA282B90@codespeak.net> Author: antocuni Date: Wed Jun 16 16:30:50 2010 New Revision: 75424 Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig.py Log: explicitly import _config_vars, as it's needed by setuptools but ignored by "import *" Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig.py Wed Jun 16 16:30:50 2010 @@ -19,5 +19,7 @@ if '__pypy__' in sys.builtin_module_names: from distutils.sysconfig_pypy import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools else: from distutils.sysconfig_cpython import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools From arigo at codespeak.net Wed Jun 16 16:39:00 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jun 2010 16:39:00 +0200 (CEST) Subject: [pypy-svn] r75425 - in pypy/trunk/pypy/rlib: . test Message-ID: <20100616143900.DEA2B282B90@codespeak.net> Author: arigo Date: Wed Jun 16 16:38:59 2010 New Revision: 75425 Modified: pypy/trunk/pypy/rlib/runicode.py pypy/trunk/pypy/rlib/test/test_runicode.py Log: Test and fix. Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Wed Jun 16 16:38:59 2010 @@ -17,7 +17,7 @@ # Note that Python3 uses a similar implementation. def UNICHR(c): assert not we_are_translated() - if c < sys.maxunicode or c > MAXUNICODE: + if c <= sys.maxunicode or c > MAXUNICODE: return unichr(c) else: c -= 0x10000 Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Wed Jun 16 16:38:59 2010 @@ -2,6 +2,16 @@ import sys, random from pypy.rlib import runicode +def test_unichr(): + a = runicode.UNICHR(0xffff) + assert a == u'\uffff' + a = runicode.UNICHR(0x10000) + if sys.maxunicode < 0x10000: + assert len(a) == 2 # surrogates + else: + assert len(a) == 1 + + class UnicodeTests(object): def typeequals(self, x, y): assert x == y From arigo at codespeak.net Wed Jun 16 17:08:04 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jun 2010 17:08:04 +0200 (CEST) Subject: [pypy-svn] r75426 - in pypy/trunk/pypy/module/_codecs: . test Message-ID: <20100616150804.D9D35282B90@codespeak.net> Author: arigo Date: Wed Jun 16 17:08:03 2010 New Revision: 75426 Modified: pypy/trunk/pypy/module/_codecs/app_codecs.py pypy/trunk/pypy/module/_codecs/test/test_codecs.py Log: Some random fixes until test_codecs passes on Mac, with a 16-bit unicode CPython and emulating a 32-bit PyPy. Modified: pypy/trunk/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/app_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/app_codecs.py Wed Jun 16 17:08:03 2010 @@ -39,8 +39,6 @@ # XXX move some of these functions to RPython (like charmap_encode, # charmap_build) to make them faster -import sys - def escape_encode( obj, errors='strict'): """None """ @@ -84,36 +82,36 @@ res = ''.join(res) return res, len(res) -if sys.maxunicode == 65535: - unicode_bytes = 2 -else: - unicode_bytes = 4 - def unicode_internal_encode( obj, errors='strict'): """None """ - if type(obj) == unicode: - p = [] - t = [ord(x) for x in obj] - for i in t: - bytes = [] - for j in xrange(unicode_bytes): - bytes += chr(i%256) - i >>= 8 - if sys.byteorder == "big": - bytes.reverse() - p += bytes - res = ''.join(p) - return res, len(res) + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 else: - res = "You can do better than this" # XXX make this right - return res, len(res) + unicode_bytes = 4 + p = [] + for x in obj: + i = ord(x) + bytes = [] + for j in xrange(unicode_bytes): + bytes += chr(i%256) + i >>= 8 + if sys.byteorder == "big": + bytes.reverse() + p += bytes + res = ''.join(p) + return res, len(res) def unicode_internal_decode( unistr, errors='strict'): - import sys if type(unistr) == unicode: return unistr, len(unistr) else: + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 + else: + unicode_bytes = 4 p = [] i = 0 if sys.byteorder == "big": @@ -541,6 +539,7 @@ hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10, 16)] def hexescape(s, pos, digits, message, errors): + import sys chr = 0 p = [] if (pos+digits>len(s)): @@ -580,6 +579,7 @@ return res, pos def PyUnicode_DecodeUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' @@ -762,6 +762,7 @@ def PyUnicode_DecodeRawUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Wed Jun 16 17:08:03 2010 @@ -84,7 +84,7 @@ assert str(UnicodeTranslateError( u"g\uffffrk", 1, 2, "ouch"))== "can't translate character u'\\uffff' in position 1: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeTranslateError( u"g\U00010000rk", 1, 2, "ouch"))== "can't translate character u'\\U00010000' in position 1: ouch" @@ -107,7 +107,7 @@ assert str(UnicodeEncodeError( "ascii", u"\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\uffff' in position 0: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", u"\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" @@ -229,7 +229,9 @@ def test_unicode_internal_encode(self): import sys - enc = u"a".encode("unicode_internal") + class U(unicode): + pass + enc = U(u"a").encode("unicode_internal") if sys.maxunicode == 65535: # UCS2 build if sys.byteorder == "big": assert enc == "\x00a" From arigo at codespeak.net Wed Jun 16 17:10:25 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jun 2010 17:10:25 +0200 (CEST) Subject: [pypy-svn] r75427 - pypy/trunk/pypy/rlib/test Message-ID: <20100616151025.3A256282B90@codespeak.net> Author: arigo Date: Wed Jun 16 17:10:23 2010 New Revision: 75427 Modified: pypy/trunk/pypy/rlib/test/test_runicode.py Log: Skip tests. Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Wed Jun 16 17:10:23 2010 @@ -227,6 +227,10 @@ self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? class TestTranslation(object): + def setup_class(cls): + if len(runicode.UNICHR(0x10000)) == 2: + py.test.skip("these tests cannot run on the llinterp") + def test_utf8(self): from pypy.rpython.test.test_llinterp import interpret def f(x): From arigo at codespeak.net Wed Jun 16 17:13:50 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jun 2010 17:13:50 +0200 (CEST) Subject: [pypy-svn] r75428 - pypy/trunk/pypy/rlib/test Message-ID: <20100616151350.6929A282B90@codespeak.net> Author: arigo Date: Wed Jun 16 17:13:49 2010 New Revision: 75428 Modified: pypy/trunk/pypy/rlib/test/test_rpoll.py Log: Fix test. Modified: pypy/trunk/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rpoll.py (original) +++ pypy/trunk/pypy/rlib/test/test_rpoll.py Wed Jun 16 17:13:49 2010 @@ -1,4 +1,4 @@ -import thread +import thread, errno from pypy.rlib.rsocket import * from pypy.rlib.rpoll import * from pypy.rpython.test.test_llinterp import interpret @@ -34,8 +34,10 @@ assert events[0][1] & POLLOUT err = cli.connect_ex(servaddr) - # win32 oddity: returns WSAEISCONN when the connection finally succeed. - assert err == 0 or err == 10056 + # win32: returns WSAEISCONN when the connection finally succeed. + # Mac OS/X: returns EISCONN. + assert (err == 0 or err == 10056 or + err == getattr(errno, 'EISCONN', '???')) events = poll({servconn.fileno(): POLLIN, cli.fileno(): POLLIN}, timeout=100) From antocuni at codespeak.net Wed Jun 16 18:24:30 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jun 2010 18:24:30 +0200 (CEST) Subject: [pypy-svn] r75429 - pypy/branch/sys-prefix/pypy/config Message-ID: <20100616162430.99A04282B90@codespeak.net> Author: antocuni Date: Wed Jun 16 18:24:29 2010 New Revision: 75429 Modified: pypy/branch/sys-prefix/pypy/config/pypyoption.py Log: cpyext is broken on the branch. Temporarly comment it out so that I can run automated tests Modified: pypy/branch/sys-prefix/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/sys-prefix/pypy/config/pypyoption.py (original) +++ pypy/branch/sys-prefix/pypy/config/pypyoption.py Wed Jun 16 18:24:29 2010 @@ -30,7 +30,7 @@ "rctime" , "select", "zipimport", "_lsprof", "crypt", "signal", "_rawffi", "termios", "zlib", "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO", - "thread", "itertools", "pyexpat", "_ssl", "cpyext"] + "thread", "itertools", "pyexpat", "_ssl"]#, "cpyext"] )) working_oo_modules = default_modules.copy() From antocuni at codespeak.net Wed Jun 16 23:30:41 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jun 2010 23:30:41 +0200 (CEST) Subject: [pypy-svn] r75430 - pypy/branch/sys-prefix/pypy Message-ID: <20100616213041.8C9FF282B90@codespeak.net> Author: antocuni Date: Wed Jun 16 23:30:38 2010 New Revision: 75430 Modified: pypy/branch/sys-prefix/pypy/pytest-A.cfg Log: remove pypy/lib from the list of directories containing applevel tests. It does no longer exists, and its applevel tests has been moved to module/test_lib_pypy, which is already included Modified: pypy/branch/sys-prefix/pypy/pytest-A.cfg ============================================================================== --- pypy/branch/sys-prefix/pypy/pytest-A.cfg (original) +++ pypy/branch/sys-prefix/pypy/pytest-A.cfg Wed Jun 16 23:30:38 2010 @@ -1,4 +1,4 @@ -cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module', 'lib'] +cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module'] interp = ['translator/goal/pypy-c'] test_driver = ['test_all.py', '-A'] From fijal at codespeak.net Thu Jun 17 04:21:05 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jun 2010 04:21:05 +0200 (CEST) Subject: [pypy-svn] r75431 - in pypy/release/1.3.x: . pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/test Message-ID: <20100617022105.CB3B2282BD6@codespeak.net> Author: fijal Date: Thu Jun 17 04:21:03 2010 New Revision: 75431 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/module/cpyext/api.py pypy/release/1.3.x/pypy/module/cpyext/cdatetime.py pypy/release/1.3.x/pypy/module/cpyext/include/datetime.h pypy/release/1.3.x/pypy/module/cpyext/state.py pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py pypy/release/1.3.x/pypy/module/cpyext/test/test_datetime.py Log: Merge 75422 from trunk Modified: pypy/release/1.3.x/pypy/module/cpyext/api.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/api.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/api.py Thu Jun 17 04:21:03 2010 @@ -315,7 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), - 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.cdatetime.build_datetime_api(space)'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'None'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -617,7 +617,7 @@ if "#" in name: continue if typ == 'PyDateTime_CAPI*': - global_objects.append('%s _%s;' % (typ, name)) + continue elif name.startswith('PyExc_'): global_objects.append('%s _%s;' % (typ[:-1], name)) else: @@ -817,8 +817,7 @@ structs.append('extern PyTypeObject _%s;' % (name,)) structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) elif typ == 'PyDateTime_CAPI*': - structs.append('extern %s _%s;' % (typ[:-1], name)) - structs.append('%s %s = &_%s;' % (typ, name, name)) + structs.append('%s %s = NULL;' % (typ, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -871,8 +870,7 @@ if typ in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': - struct_ptr = w_obj - name = '_' + name + continue else: assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj Modified: pypy/release/1.3.x/pypy/module/cpyext/cdatetime.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/cdatetime.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/cdatetime.py Thu Jun 17 04:21:03 2010 @@ -1,9 +1,11 @@ from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import PyObject, make_ref +from pypy.rlib.objectmodel import we_are_translated +from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) from pypy.module.cpyext.import_ import PyImport_Import from pypy.module.cpyext.typeobject import PyTypeObjectPtr +from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_renamer @@ -17,10 +19,16 @@ ('DeltaType', PyTypeObjectPtr), )) -def build_datetime_api(space): - w_datetime = PyImport_Import(space, space.wrap("datetime")) + at cpython_api([], lltype.Ptr(PyDateTime_CAPI), + error=lltype.nullptr(PyDateTime_CAPI)) +def _PyDateTime_Import(space): datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw') + if not we_are_translated(): + datetimeAPI_dealloc(space) + space.fromcache(State).datetimeAPI = datetimeAPI + + w_datetime = PyImport_Import(space, space.wrap("datetime")) w_type = space.getattr(w_datetime, space.wrap("date")) datetimeAPI.c_DateType = rffi.cast( PyTypeObjectPtr, make_ref(space, w_type)) @@ -36,9 +44,19 @@ return datetimeAPI - at cpython_api([], PyObject) -def _PyDateTime_Import(space): - return +def datetimeAPI_dealloc(space): + "Used in tests only, to please the refcount checker" + if we_are_translated(): + return + datetimeAPI = space.fromcache(State).datetimeAPI + if datetimeAPI is None: + return + space.fromcache(State).datetimeAPI = None + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateTimeType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_TimeType)) + Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DeltaType)) + lltype.free(datetimeAPI, flavor='raw') PyDateTime_Date = PyObject PyDateTime_Time = PyObject Modified: pypy/release/1.3.x/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/include/datetime.h (original) +++ pypy/release/1.3.x/pypy/module/cpyext/include/datetime.h Thu Jun 17 04:21:03 2010 @@ -14,7 +14,11 @@ } PyDateTime_CAPI; PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; -#define PyDateTime_IMPORT _PyDateTime_Import() +#define PyDateTime_IMPORT \ + do { \ + if(PyDateTimeAPI==NULL) \ + PyDateTimeAPI = _PyDateTime_Import(); \ + } while (0) typedef struct { PyObject_HEAD Modified: pypy/release/1.3.x/pypy/module/cpyext/state.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/state.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/state.py Thu Jun 17 04:21:03 2010 @@ -5,6 +5,8 @@ class State: + datetimeAPI = None # used in tests + def __init__(self, space): self.space = space self.reset() Modified: pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/test/test_cpyext.py Thu Jun 17 04:21:03 2010 @@ -271,6 +271,8 @@ Py_DecRef(self.space, w_obj) state.non_heaptypes_w[:] = [] state.reset_borrowed_references() + from pypy.module.cpyext import cdatetime + cdatetime.datetimeAPI_dealloc(self.space) if self.check_and_print_leaks(): assert False, "Test leaks or loses object(s)." Modified: pypy/release/1.3.x/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/test/test_datetime.py Thu Jun 17 04:21:03 2010 @@ -85,6 +85,7 @@ module = self.import_extension('foo', [ ("get_types", "METH_NOARGS", """ + PyDateTime_IMPORT; return PyTuple_Pack(4, PyDateTimeAPI->DateType, PyDateTimeAPI->DateTimeType, From antocuni at codespeak.net Thu Jun 17 10:44:18 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jun 2010 10:44:18 +0200 (CEST) Subject: [pypy-svn] r75432 - pypy/branch/sys-prefix/pypy/bin Message-ID: <20100617084418.5BA89282BD6@codespeak.net> Author: antocuni Date: Thu Jun 17 10:44:16 2010 New Revision: 75432 Modified: pypy/branch/sys-prefix/pypy/bin/py.py Log: make sure to call pypy_initial_path when running py.py, which sets sys.prefix&co. This is needed by site.py nowadays Modified: pypy/branch/sys-prefix/pypy/bin/py.py ============================================================================== --- pypy/branch/sys-prefix/pypy/bin/py.py (original) +++ pypy/branch/sys-prefix/pypy/bin/py.py Thu Jun 17 10:44:16 2010 @@ -11,6 +11,7 @@ except ImportError: pass +import pypy from pypy.tool import option from optparse import make_option from pypy.interpreter import main, interactive, error, gateway @@ -84,6 +85,14 @@ space.setitem(space.sys.w_dict, space.wrap('executable'), space.wrap(argv[0])) + # call pypy_initial_path: the side-effect is that it sets sys.prefix and + # sys.exec_prefix + srcdir = os.path.dirname(os.path.dirname(pypy.__file__)) + space.appexec([space.wrap(srcdir)], """(srcdir): + import sys + sys.pypy_initial_path(srcdir) + """) + # set warning control options (if any) warn_arg = interactiveconfig.warn if warn_arg is not None: From antocuni at codespeak.net Thu Jun 17 13:35:50 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jun 2010 13:35:50 +0200 (CEST) Subject: [pypy-svn] r75433 - in pypy/branch/sys-prefix: lib/pypy1.2/lib-python/modified-2.5.2/distutils lib/pypy1.2/lib-python/modified-2.5.2/distutils/command lib/pypy1.2/lib-python/modified-2.5.2/test pypy pypy/module/sys Message-ID: <20100617113550.CF3E7282BD6@codespeak.net> Author: antocuni Date: Thu Jun 17 13:35:46 2010 New Revision: 75433 Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/regrtest.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_doctest.py pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_sys.py pypy/branch/sys-prefix/pypy/module/sys/__init__.py pypy/branch/sys-prefix/pypy/module/sys/state.py pypy/branch/sys-prefix/pypy/test_all.py Log: This is a (hopefully temporary) hack. Currently buildbot assumes that lib-python is under trunk/ and invokes lib-python tests like this: python pypy/test_all.py --pypy=pypy/translator/goal/pypy-c \ --resultlog=cpython.log lib-python However, now lib-python is under lib/pypy1.2/lib-python. We cannot just change buildbot, as it would break all the other current branches, so instead we replace lib-python with the correct path here. Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/build_ext.py Thu Jun 17 13:35:46 2010 @@ -167,7 +167,7 @@ # for Release and Debug builds. # also Python's library directory must be appended to library_dirs if os.name == 'nt': - self.library_dirs.append(os.path.join(sys.pypy_prefix, 'pypy', '_interfaces')) + self.library_dirs.append(os.path.join(sys.prefix, 'pypy', '_interfaces')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/command/install.py Thu Jun 17 13:35:46 2010 @@ -392,13 +392,9 @@ if self.exec_prefix is not None: raise DistutilsOptionError, \ "must not supply exec-prefix without prefix" - - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - self.exec_prefix = self.prefix - else: - self.prefix = os.path.normpath(sys.prefix) - self.exec_prefix = os.path.normpath(sys.exec_prefix) + + self.prefix = os.path.normpath(sys.prefix) + self.exec_prefix = os.path.normpath(sys.exec_prefix) else: if self.exec_prefix is None: @@ -418,10 +414,7 @@ self.select_scheme("unix_home") else: if self.prefix is None: - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - else: - self.prefix = os.path.normpath(sys.prefix) + self.prefix = os.path.normpath(sys.prefix) self.install_base = self.install_platbase = self.prefix try: @@ -435,7 +428,7 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! - if hasattr(sys, 'pypy_prefix'): + if hasattr(sys, 'pypy_version_info'): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Thu Jun 17 13:35:46 2010 @@ -7,15 +7,15 @@ from distutils.errors import DistutilsPlatformError -PYPY_PREFIX = os.path.normpath(sys.pypy_prefix) +PREFIX = os.path.normpath(sys.prefix) python_build = False def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j if plat_specific: - return j(sys.pypy_prefix, "pypy", "_interfaces") - return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') + return j(sys.prefix, "pypy", "_interfaces") + return j(sys.prefix, 'pypy', 'module', 'cpyext', 'include') def get_python_version(): """Return a string containing the major and minor Python version, @@ -43,7 +43,7 @@ raise DistutilsPlatformError( "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: - prefix = PYPY_PREFIX + prefix = PREFIX pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] return os.path.join(prefix, 'lib', pypylib, 'site-packages') Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/regrtest.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/regrtest.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/regrtest.py Thu Jun 17 13:35:46 2010 @@ -348,11 +348,8 @@ random.shuffle(tests) if trace: import trace - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=False, count=True) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], + trace=False, count=True) test_support.verbose = verbose # Tell tests to be moderately quiet test_support.use_resources = use_resources save_modules = sys.modules.keys() Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_doctest.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_doctest.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_doctest.py Thu Jun 17 13:35:46 2010 @@ -2422,11 +2422,8 @@ import trace, sys, re, StringIO def test_coverage(coverdir): - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=0, count=1) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,], + trace=0, count=1) tracer.run('reload(doctest); test_main()') r = tracer.results() print 'Writing coverage results...' Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_sys.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_sys.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/modified-2.5.2/test/test_sys.py Thu Jun 17 13:35:46 2010 @@ -334,11 +334,8 @@ if test.test_support.have_unicode: self.assert_(isinstance(sys.maxunicode, int)) self.assert_(isinstance(sys.platform, basestring)) - if hasattr(sys, 'prefix'): - self.assert_(isinstance(sys.prefix, basestring)) - self.assert_(isinstance(sys.exec_prefix, basestring)) - else: - self.assert_(isinstance(sys.pypy_prefix, basestring)) # PyPy only + self.assert_(isinstance(sys.prefix, basestring)) + self.assert_(isinstance(sys.exec_prefix, basestring)) self.assert_(isinstance(sys.version, basestring)) vi = sys.version_info self.assert_(isinstance(vi, tuple)) Modified: pypy/branch/sys-prefix/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/__init__.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/__init__.py Thu Jun 17 13:35:46 2010 @@ -29,9 +29,8 @@ 'stderr' : 'state.getio(space).w_stderr', '__stderr__' : 'state.getio(space).w_stderr', 'pypy_objspaceclass' : 'space.wrap(repr(space))', - #'pypy_prefix': added by pypy_initial_path() when it succeeds, pointing - # to the trunk of a checkout or to the dir /usr/share/pypy-1.1 . - + #'prefix' : # added by pypy_initial_path() when it + #'exec_prefix' : # succeeds, pointing to trunk or /usr 'path' : 'state.get(space).w_path', 'modules' : 'state.get(space).w_modules', 'argv' : 'state.get(space).w_argv', Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/state.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/state.py Thu Jun 17 13:35:46 2010 @@ -64,8 +64,6 @@ except OSError: return space.w_None else: - space.setitem(space.sys.w_dict, space.wrap('pypy_prefix'), # XXX remove me - space.wrap(srcdir)) space.setitem(space.sys.w_dict, space.wrap('prefix'), space.wrap(srcdir)) space.setitem(space.sys.w_dict, space.wrap('exec_prefix'), Modified: pypy/branch/sys-prefix/pypy/test_all.py ============================================================================== --- pypy/branch/sys-prefix/pypy/test_all.py (original) +++ pypy/branch/sys-prefix/pypy/test_all.py Thu Jun 17 13:35:46 2010 @@ -1,6 +1,34 @@ #! /usr/bin/env python +def fix_lib_python_path(): + """ + This is a (hopefully temporary) hack. + + Currently buildbot assumes that lib-python is under trunk/ and invokes + lib-python tests like this: + + python pypy/test_all.py --pypy=pypy/translator/goal/pypy-c \ + --resultlog=cpython.log lib-python + + However, now lib-python is under lib/pypy1.2/lib-python. We cannot just + change buildbot, as it would break all the other current branches, so + instead we replace lib-python with the correct path here. + """ + import sys + from pypy.tool.lib_pypy import LIB_PYTHON + if sys.argv and sys.argv[-1].endswith('lib-python'): + libpython = py.path.local(sys.argv[-1]) + if libpython.check(dir=True): + # the argument passed to the command line actually exists, so no + # need to patch it + return + else: + # patch it with the correct path + sys.argv[-1] = str(LIB_PYTHON) + + if __name__ == '__main__': import tool.autopath import py + fix_lib_python_path() py.cmdline.pytest() From afa at codespeak.net Thu Jun 17 15:03:51 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 17 Jun 2010 15:03:51 +0200 (CEST) Subject: [pypy-svn] r75435 - in pypy/trunk/pypy/module/cpyext: . include Message-ID: <20100617130351.59DD4282BEF@codespeak.net> Author: afa Date: Thu Jun 17 15:03:49 2010 New Revision: 75435 Modified: pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/include/Python.h Log: Fix compilation with --cc=mingw32 Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Thu Jun 17 15:03:49 2010 @@ -736,6 +736,7 @@ ("SIZEOF_INT", rffi.INT) ]: pypy_macros.append("#define %s %s" % (macro_name, rffi.sizeof(size))) + pypy_macros.append('') pypy_macros_h = udir.join('pypy_macros.h') pypy_macros_h.write('\n'.join(pypy_macros)) Modified: pypy/trunk/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/trunk/pypy/module/cpyext/include/Python.h (original) +++ pypy/trunk/pypy/module/cpyext/include/Python.h Thu Jun 17 15:03:49 2010 @@ -18,6 +18,9 @@ # ifdef _MSC_VER # include # endif +# ifdef __MINGW32__ +# include +# endif # include # define Py_DEPRECATED(VERSION_UNUSED) # ifdef Py_BUILD_CORE From cfbolz at codespeak.net Thu Jun 17 17:02:27 2010 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jun 2010 17:02:27 +0200 (CEST) Subject: [pypy-svn] r75436 - pypy/trunk/pypy/jit/tl/tla Message-ID: <20100617150227.B9316282BD6@codespeak.net> Author: cfbolz Date: Thu Jun 17 17:02:24 2010 New Revision: 75436 Modified: pypy/trunk/pypy/jit/tl/tla/targettla.py Log: policy is in a different place now Modified: pypy/trunk/pypy/jit/tl/tla/targettla.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tla/targettla.py (original) +++ pypy/trunk/pypy/jit/tl/tla/targettla.py Thu Jun 17 17:02:24 2010 @@ -28,7 +28,7 @@ def target(driver, args): return entry_point, None -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() From getxsick at codespeak.net Thu Jun 17 19:40:27 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 17 Jun 2010 19:40:27 +0200 (CEST) Subject: [pypy-svn] r75438 - pypy/trunk/pypy/module/_rawffi Message-ID: <20100617174027.66737282BF9@codespeak.net> Author: getxsick Date: Thu Jun 17 19:40:25 2010 New Revision: 75438 Modified: pypy/trunk/pypy/module/_rawffi/array.py pypy/trunk/pypy/module/_rawffi/structure.py Log: kill redundant imports Modified: pypy/trunk/pypy/module/_rawffi/array.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/array.py (original) +++ pypy/trunk/pypy/module/_rawffi/array.py Thu Jun 17 19:40:25 2010 @@ -8,7 +8,7 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror +from pypy.interpreter.error import OperationError from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value Modified: pypy/trunk/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/structure.py (original) +++ pypy/trunk/pypy/module/_rawffi/structure.py Thu Jun 17 19:40:25 2010 @@ -9,7 +9,7 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror, operationerrfmt +from pypy.interpreter.error import OperationError, operationerrfmt from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value From arigo at codespeak.net Thu Jun 17 19:49:57 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jun 2010 19:49:57 +0200 (CEST) Subject: [pypy-svn] r75439 - in pypy/trunk/pypy: rpython/memory/gctransform translator/c/gcc translator/c/gcc/test translator/c/src Message-ID: <20100617174957.A7781282BEF@codespeak.net> Author: arigo Date: Thu Jun 17 19:49:55 2010 New Revision: 75439 Modified: pypy/trunk/pypy/rpython/memory/gctransform/asmgcroot.py pypy/trunk/pypy/translator/c/gcc/test/test_asmgcroot.py pypy/trunk/pypy/translator/c/gcc/trackgcroot.py pypy/trunk/pypy/translator/c/src/mem.h Log: Fix for test_asmgcroot on MacOS (and probably other platforms). Done by moving the declaration of gcrootanchor out of gcmaptable.s. Modified: pypy/trunk/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/asmgcroot.py Thu Jun 17 19:49:55 2010 @@ -114,12 +114,14 @@ fnptr._obj._name + '_reload', graph=graph2) c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2)], FUNC1.RESULT) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], resulttype=lltype.Ptr(HELPERFUNC)) hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, Constant(None, lltype.Void)], + [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, + Constant(None, lltype.Void)], resultvar=hop.spaceop.result) self.pop_roots(hop, livevars) @@ -151,7 +153,8 @@ def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata gcdata._gc_collect_stack_root = collect_stack_root - pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback)) + pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback), + gcrootanchor) def walk_stack_from(self): curframe = lltype.malloc(WALKFRAME, flavor='raw') @@ -160,7 +163,7 @@ # Walk over all the pieces of stack. They are in a circular linked # list of structures of 7 words, the 2 first words being prev/next. # The anchor of this linked list is: - anchor = llop.gc_asmgcroot_static(llmemory.Address, 3) + anchor = llmemory.cast_ptr_to_adr(gcrootanchor) initialframedata = anchor.address[1] stackscount = 0 while initialframedata != anchor: # while we have not looped back @@ -475,8 +478,22 @@ llmemory.Address), ) +# We have a circular doubly-linked list of all the ASM_FRAMEDATAs currently +# alive. The list's starting point is given by 'gcrootanchor', which is not +# a full ASM_FRAMEDATA but only contains the prev/next pointers: +ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference()) +ASM_FRAMEDATA_HEAD_PTR.TO.become(lltype.Struct('ASM_FRAMEDATA_HEAD', + ('prev', ASM_FRAMEDATA_HEAD_PTR), + ('next', ASM_FRAMEDATA_HEAD_PTR) + )) +gcrootanchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, immortal=True) +gcrootanchor.prev = gcrootanchor +gcrootanchor.next = gcrootanchor +c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', - [ASM_CALLBACK_PTR], + [ASM_CALLBACK_PTR, + ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True) Modified: pypy/trunk/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/test/test_asmgcroot.py Thu Jun 17 19:49:55 2010 @@ -65,8 +65,13 @@ env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),) else: env = '' - g = os.popen( - '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + cwd = os.getcwd() + try: + os.chdir(str(exe_name.dirpath())) + g = os.popen( + '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + finally: + os.chdir(cwd) for line in g: print >> sys.stderr, 'RUN:', line.rstrip() lines.append(line) Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Thu Jun 17 19:49:55 2010 @@ -1283,20 +1283,13 @@ if self.format == 'msvc': print >> output, """\ - /* A circular doubly-linked list of all - * the ASM_FRAMEDATAs currently alive - */ - struct asm_framedata { - struct asm_framedata* prev; - struct asm_framedata* next; - } __gcrootanchor = { &__gcrootanchor, &__gcrootanchor }; - /* See description in asmgcroot.py */ __declspec(naked) long pypy_asm_stackwalk(void *callback) { __asm { - mov\tedx, DWORD PTR [esp+4]\t; my argument, which is the callback + mov\tedx, DWORD PTR [esp+4]\t; 1st argument, which is the callback + mov\tecx, DWORD PTR [esp+8]\t; 2nd argument, which is gcrootanchor mov\teax, esp\t\t; my frame top address push\teax\t\t\t; ASM_FRAMEDATA[6] push\tebp\t\t\t; ASM_FRAMEDATA[5] @@ -1307,10 +1300,10 @@ ; Add this ASM_FRAMEDATA to the front of the circular linked ; list. Let's call it 'self'. - mov\teax, DWORD PTR [__gcrootanchor+4]\t\t; next = gcrootanchor->next + mov\teax, DWORD PTR [ecx+4]\t\t; next = gcrootanchor->next push\teax\t\t\t\t\t\t\t\t\t; self->next = next - push\tOFFSET __gcrootanchor ; self->prev = gcrootanchor - mov\tDWORD PTR [__gcrootanchor+4], esp\t\t; gcrootanchor->next = self + push\tecx ; self->prev = gcrootanchor + mov\tDWORD PTR [ecx+4], esp\t\t; gcrootanchor->next = self mov\tDWORD PTR [eax+0], esp\t\t\t\t\t; next->prev = self call\tedx\t\t\t\t\t\t; invoke the callback @@ -1343,7 +1336,8 @@ print >> output, """\ /* See description in asmgcroot.py */ - movl\t4(%esp), %edx\t/* my argument, which is the callback */ + movl\t4(%esp), %edx\t/* 1st argument, which is the callback */ + movl\t8(%esp), %ecx\t/* 2nd argument, which is gcrootanchor */ movl\t%esp, %eax\t/* my frame top address */ pushl\t%eax\t\t/* ASM_FRAMEDATA[6] */ pushl\t%ebp\t\t/* ASM_FRAMEDATA[5] */ @@ -1354,10 +1348,10 @@ /* Add this ASM_FRAMEDATA to the front of the circular linked */ /* list. Let's call it 'self'. */ - movl\t__gcrootanchor + 4, %eax\t/* next = gcrootanchor->next */ + movl\t4(%ecx), %eax\t/* next = gcrootanchor->next */ pushl\t%eax\t\t\t\t/* self->next = next */ - pushl\t$__gcrootanchor\t\t\t/* self->prev = gcrootanchor */ - movl\t%esp, __gcrootanchor + 4\t/* gcrootanchor->next = self */ + pushl\t%ecx\t\t\t/* self->prev = gcrootanchor */ + movl\t%esp, 4(%ecx)\t/* gcrootanchor->next = self */ movl\t%esp, 0(%eax)\t\t\t/* next->prev = self */ /* note: the Mac OS X 16 bytes aligment must be respected. */ @@ -1378,7 +1372,7 @@ /* the return value is the one of the 'call' above, */ /* because %eax (and possibly %edx) are unmodified */ ret - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) + """ _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk', darwin='', @@ -1388,17 +1382,6 @@ for label, state, is_range in self.gcmaptable: label = label[1:] print >> output, "extern void* %s;" % label - else: - print >> output, """\ - /* A circular doubly-linked list of all */ - /* the ASM_FRAMEDATAs currently alive */ - .data - .align 4 - .globl __gcrootanchor - __gcrootanchor: - .long\t__gcrootanchor /* prev */ - .long\t__gcrootanchor /* next */ - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) shapes = {} shapelines = [] @@ -1437,6 +1420,8 @@ """ else: print >> output, """\ + .data + .align 4 .globl __gcmapstart __gcmapstart: """.replace("__gcmapstart", _globalname("__gcmapstart")) Modified: pypy/trunk/pypy/translator/c/src/mem.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/mem.h (original) +++ pypy/trunk/pypy/translator/c/src/mem.h Thu Jun 17 19:49:55 2010 @@ -6,8 +6,7 @@ extern char __gcmapstart; extern char __gcmapend; extern char __gccallshapes; -extern void *__gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); #define __gcnoreorderhack __gcmapend /* The following pseudo-instruction is used by --gcrootfinder=asmgcc @@ -47,15 +46,13 @@ i == 0 ? (void*)&__gcmapstart : \ i == 1 ? (void*)&__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #else extern void* __gcmapstart; extern void* __gcmapend; extern char* __gccallshapes; -extern void* __gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); /* With the msvc Microsoft Compiler, the optimizer seems free to move any code (even asm) that involves local memory (registers and stack). @@ -82,7 +79,6 @@ i == 0 ? (void*)__gcmapstart : \ i == 1 ? (void*)__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #endif From jcreigh at codespeak.net Thu Jun 17 20:55:22 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Thu, 17 Jun 2010 20:55:22 +0200 (CEST) Subject: [pypy-svn] r75440 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100617185522.5218E282BD6@codespeak.net> Author: jcreigh Date: Thu Jun 17 20:55:19 2010 New Revision: 75440 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py Log: random rpython fixes/hacks Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Thu Jun 17 20:55:19 2010 @@ -183,26 +183,6 @@ self._build_malloc_fixedsize_slowpath() def _build_float_constants(self): - """ - # 11 words: 8 words for the data, and up to 3 words for alignment - addr = lltype.malloc(rffi.CArray(lltype.Signed), 11, flavor='raw') - if not we_are_translated(): - self._keepalive_malloced_float_consts = addr - float_constants = rffi.cast(lltype.Signed, addr) - float_constants = (float_constants + 15) & ~15 # align to 16 bytes - addr = rffi.cast(rffi.CArrayPtr(lltype.Signed), float_constants) - addr[0] = 0 # \ - addr[1] = -2147483648 # / for neg - addr[2] = 0 # - addr[3] = 0 # - addr[4] = -1 # \ - addr[5] = 2147483647 # / for abs - addr[6] = 0 # - addr[7] = 0 # - self.float_const_neg_addr = float_constants - self.float_const_abs_addr = float_constants + 16 - """ - # 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw') if not we_are_translated(): @@ -214,8 +194,8 @@ neg_const = '\x00\x00\x00\x00\x00\x00\x00\x80' abs_const = '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F' data = neg_const + qword_padding + abs_const + qword_padding - for i, char in enumerate(data): - addr[i] = char + for i in range(len(data)): + addr[i] = data[i] self.float_const_neg_addr = float_constants self.float_const_abs_addr = float_constants + 16 @@ -384,8 +364,8 @@ def _call_footer(self, mc): mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD) - for regloc in reversed(self.cpu.CALLEE_SAVE_REGISTERS): - mc.POP(regloc) + for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1): + mc.POP(self.cpu.CALLEE_SAVE_REGISTERS[i]) mc.POP(ebp) mc.RET() @@ -426,6 +406,9 @@ return adr_stackadjust def _assemble_bootstrap_direct_call_64(self, arglocs, jmpadr, stackdepth): + # XXX: Is this even remotely correct? Might arglocs contain some of + # the same locations that the calling convention uses? + # In reverse order for use with pop() unused_gpr = [r9, r8, ecx, edx, esi, edi] unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0] @@ -434,18 +417,24 @@ adr_stackadjust = self._call_header() self._patch_stackadjust(adr_stackadjust, stackdepth) - for i, loc in enumerate(nonfloatlocs): - if loc != None: + for i in range(len(nonfloatlocs)): + loc = nonfloatlocs[i] + if loc is not None: if len(unused_gpr) > 0: self.mc.MOV(loc, unused_gpr.pop()) else: self.mc.MOV_rb(X86_64_SCRATCH_REG.value, (2 + i) * WORD) self.mc.MOV(loc, X86_64_SCRATCH_REG) - for i, loc in enumerate(floatlocs): - if loc != None: + for i in range(len(floatlocs)): + loc = floatlocs[i] + if loc is not None: if len(unused_xmm) > 0: self.mc.MOVSD(loc, unused_xmm.pop()) + else: + self.mc.MOVSD_xb(X86_64_XMM_SCRATCH_REG.value, (2 + i) * WORD) + self.mc.MOVSD(loc, X86_64_XMM_SCRATCH_REG) + self.mc.JMP_l(jmpadr) @@ -660,6 +649,9 @@ return self.implement_guard(addr, false_cond) return genop_cmp_guard_float + # We need to specialize on force_mc because if force_mc is True, "mc" will + # be a MachineCodeBlock, whereas if it is False, "mc" will be a + # MachineCodeBlockWrapper @specialize.arg(5) def _emit_call(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): @@ -694,6 +686,7 @@ mc.CALL(x) self.mark_gc_roots() + @specialize.arg(5) def _emit_call_64(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): if not force_mc: mc = self.mc @@ -721,7 +714,8 @@ pass_on_stack.append(loc) # Emit instructions to pass the stack arguments - for i, loc in enumerate(pass_on_stack): + for i in range(len(pass_on_stack)): + loc = pass_on_stack[i] if isinstance(loc, StackLoc): if loc.type == FLOAT: mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) @@ -767,7 +761,8 @@ for reg, loc in items: mc.PUSH(loc) - for reg, loc in reversed(items): + for i in range(len(items)-1, -1, -1): + reg, loc = items[i] mc.POP(reg) self._regalloc.reserve_param(len(pass_on_stack)) @@ -1451,7 +1446,7 @@ recovery_addr = mc.tell() # Push all general purpose registers - for gpr in reversed(range(self.cpu.NUM_REGS)): + for gpr in range(self.cpu.NUM_REGS-1, -1, -1): mc.PUSH_r(gpr) # ebx/rbx is callee-save in both i386 and x86-64 @@ -1496,7 +1491,9 @@ # now we return from the complete frame, which starts from # _assemble_bootstrap_code(). The LEA below throws away most # of the frame, including all the PUSHes that we did just above. - self._call_footer(mc) + + # XXX: using self.mc2 instead of mc to make translation pass + self._call_footer(self.mc2) self.mc2.done() self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Thu Jun 17 20:55:19 2010 @@ -2,6 +2,7 @@ from pypy.jit.backend.x86 import rx86 from pypy.rlib.unroll import unrolling_iterable from pypy.jit.backend.x86.arch import WORD +from pypy.tool.sourcetools import func_with_new_name # # This module adds support for "locations", which can be either in a Const, @@ -23,6 +24,8 @@ def value_j(self): return self.value def value_i(self): return self.value def value_x(self): return self.value + def value_a(self): raise AssertionError("value_a undefined") + def value_m(self): raise AssertionError("value_m undefined") class StackLoc(AssemblerLocation): _immutable_ = True @@ -177,18 +180,33 @@ self.POP_r(eax.value) else: self.MOV_ri(X86_64_SCRATCH_REG.value, val2) - getattr(self, name + "_" + possible_code1 + "r")(val1, X86_64_SCRATCH_REG.value) + methname = name + "_" + possible_code1 + "r" + if hasattr(rx86.AbstractX86CodeBuilder, methname): + getattr(self, methname)(val1, X86_64_SCRATCH_REG.value) + else: + assert False, "a" elif self.WORD == 8 and possible_code1 == 'j': self.MOV_ri(X86_64_SCRATCH_REG.value, val1) - getattr(self, name + "_" + "m" + possible_code2)((X86_64_SCRATCH_REG.value, 0), val2) + methname = name + "_" + "m" + possible_code2 + if hasattr(rx86.AbstractX86CodeBuilder, methname): + getattr(self, methname)((X86_64_SCRATCH_REG.value, 0), val2) + else: + assert False, "b" elif self.WORD == 8 and possible_code2 == 'j': self.MOV_ri(X86_64_SCRATCH_REG.value, val2) - getattr(self, name + "_" + possible_code1 + "m")(val1, (X86_64_SCRATCH_REG.value, 0)) + methname = name + "_" + possible_code1 + "m" + if hasattr(rx86.AbstractX86CodeBuilder, methname): + getattr(self, methname)(val1, (X86_64_SCRATCH_REG.value, 0)) + else: + assert False, "c" else: methname = name + "_" + possible_code1 + possible_code2 - getattr(self, methname)(val1, val2) + if hasattr(rx86.AbstractX86CodeBuilder, methname): + getattr(self, methname)(val1, val2) + else: + assert False, "d" - return INSN + return func_with_new_name(INSN, "INSN_" + name) def _unaryop(name): def INSN(self, loc): @@ -196,15 +214,14 @@ for possible_code in unrolling_location_codes: if code == possible_code: methname = name + "_" + possible_code - # if hasattr(rx86.AbstractX86CodeBuilder, methname): - if hasattr(self, methname): + if hasattr(rx86.AbstractX86CodeBuilder, methname): val = getattr(loc, "value_" + possible_code)() getattr(self, methname)(val) return else: raise AssertionError("Instruction not defined: " + methname) - return INSN + return func_with_new_name(INSN, "INSN_" + name) def _16_bit_binaryop(name): def INSN(self, loc1, loc2): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Thu Jun 17 20:55:19 2010 @@ -515,6 +515,10 @@ CVTTSD2SI_rx = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), register(2), '\xC0') CVTTSD2SI_rb = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), stack_bp(2)) + # XXX: hack + def CALL_j(self): + assert False + # ------------------------------------------------------------ Conditions = { Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py Thu Jun 17 20:55:19 2010 @@ -3,13 +3,14 @@ from pypy.rlib.jit import JitDriver, OPTIMIZER_FULL, unroll_parameters from pypy.rlib.jit import PARAMETERS, dont_look_inside from pypy.jit.metainterp.jitprof import Profiler -from pypy.jit.backend.x86.runner import CPU386 +from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.test.support import CCompiledMixin from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.translator.translator import TranslationContext +from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 class TestTranslationX86(CCompiledMixin): - CPUClass = CPU386 + CPUClass = getcpuclass() def _check_cbuilder(self, cbuilder): # We assume here that we have sse2. If not, the CPUClass @@ -114,7 +115,7 @@ class TestTranslationRemoveTypePtrX86(CCompiledMixin): - CPUClass = CPU386 + CPUClass = getcpuclass() def _get_TranslationContext(self): t = TranslationContext() @@ -125,6 +126,10 @@ return t def test_external_exception_handling_translates(self): + # FIXME + if IS_X86_64: + import py.test; py.test.skip() + jitdriver = JitDriver(greens = [], reds = ['n', 'total']) @dont_look_inside From fijal at codespeak.net Thu Jun 17 22:48:39 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jun 2010 22:48:39 +0200 (CEST) Subject: [pypy-svn] r75441 - pypy/trunk/pypy/module/_rawffi/test Message-ID: <20100617204839.C032D282BD6@codespeak.net> Author: fijal Date: Thu Jun 17 22:48:36 2010 New Revision: 75441 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Log: Write a failing test Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Thu Jun 17 22:48:36 2010 @@ -160,6 +160,17 @@ { return 42; } + + typedef union { + short x; + long y; + } UN; + + UN ret_un_func(UN inp) + { + inp.y = inp.x * 100; + return inp; + } ''')) symbols = """get_char char_check get_raw_pointer @@ -928,6 +939,17 @@ assert a[3] == 'z' assert a[4] == 't' + def test_union(self): + skip("segfaulting") + import _rawffi + longsize = _rawffi.sizeof('l') + S = _rawffi.Structure((longsize, longsize)) + s = S(autofree=False) + lib = _rawffi.CDLL(self.lib_name) + f = lib.ptr('ret_un_func', [(S, 1)], (S, 1)) + ret = f(s) + s.free() + class AppTestAutoFree: def setup_class(cls): space = gettestobjspace(usemodules=('_rawffi', 'struct')) From getxsick at codespeak.net Thu Jun 17 23:04:31 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 17 Jun 2010 23:04:31 +0200 (CEST) Subject: [pypy-svn] r75442 - in pypy/branch/fast-ctypes/pypy/module/jitffi: . test Message-ID: <20100617210431.28967282BD6@codespeak.net> Author: getxsick Date: Thu Jun 17 23:04:29 2010 New Revision: 75442 Added: pypy/branch/fast-ctypes/pypy/module/jitffi/ (props changed) pypy/branch/fast-ctypes/pypy/module/jitffi/__init__.py (contents, props changed) pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (contents, props changed) pypy/branch/fast-ctypes/pypy/module/jitffi/test/ (props changed) pypy/branch/fast-ctypes/pypy/module/jitffi/test/__init__.py (contents, props changed) pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (contents, props changed) Log: module/jitffi is back. it doesn't work, just initial check in. Added: pypy/branch/fast-ctypes/pypy/module/jitffi/__init__.py ============================================================================== --- (empty file) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/__init__.py Thu Jun 17 23:04:29 2010 @@ -0,0 +1,8 @@ +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + interpleveldefs = { + 'CDLL' : 'interp_jitffi.W_CDLL', + } + + appleveldefs = {} Added: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- (empty file) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Thu Jun 17 23:04:29 2010 @@ -0,0 +1,32 @@ +from pypy.rlib import rjitffi +from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable +from pypy.interpreter.error import wrap_oserror +from pypy.interpreter.gateway import interp2app +from pypy.interpreter.typedef import TypeDef + +class W_CDLL(Wrappable, rjitffi.CDLL): + def __init__(self, space, name): + self.space = space + super(W_CDLL, self).__init__(name) + + def get_w(self, func, w_args_type, res_type='void'): + args_type_w = [ self.space.str_w(w_x) + for w_x in self.space.listview(w_args_type) ] + return self.space.wrap(self.get(func, args_type_w, res_type)) + +def descr_new_cdll(space, w_type, name): + try: + return space.wrap(W_CDLL(space, name)) + except OSError, e: + raise wrap_oserror(space, e) +descr_new_cdll.unwrap_spec = [ObjSpace, W_Root, str] + +W_CDLL.typedef = TypeDef( + 'CDLL', + __new__ = interp2app(descr_new_cdll), + get = interp2app(W_CDLL.get_w, unwrap_spec=['self', + str, W_Root, str]), + __doc__ = """ C Dynamically loaded library +use CDLL(libname) to create a handle to a C library (the argument is processed +the same way as dlopen processes it).""" +) Added: pypy/branch/fast-ctypes/pypy/module/jitffi/test/__init__.py ============================================================================== Added: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- (empty file) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Thu Jun 17 23:04:29 2010 @@ -0,0 +1,97 @@ +from pypy.conftest import gettestobjspace +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.platform import platform + +import py + +class AppTestJitffi(object): + @staticmethod + def preprare_c_example(): + from pypy.tool.udir import udir + c_file = udir.ensure("test_jitffi", dir=True).join("xlib.c") + c_file.write(py.code.Source(''' + int add_integers(int a, int b) + { + return a+b; + } + + double add_floats(double a, double b) + { + return a+b; + } + + double return_float(int a, int b) + { + return a+b; + } + + int max3(int a, int b, int c) + { + int max = a; + if (b > max) max = b; + if (c > max) max = c; + return max; + } + + int fvoid(void) + { + return 1; + } + + void return_void(int a, int b) + { + int c; + c = a + b; + } + ''' + )) + + symbols = ['add_integers', 'add_floats', 'return_float', + 'max3', 'fvoid', 'return_void'] + eci = ExternalCompilationInfo(export_symbols=symbols) + + return str(platform.compile([c_file], eci, 'x', standalone=False)) + + def setup_class(cls): + space = gettestobjspace(usemodules=('jitffi',)) + cls.space = space + cls.w_lib_name = space.wrap(cls.preprare_c_example()) + + #def test_missing_lib(self): + # py.test.raises(OSError, rjitffi.CDLL, 'xxxfoo888baryyy') + + def test_get(self): + import jitffi + lib = jitffi.CDLL(self.lib_name) + + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 3 == func.call(1,2) + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 1 == func.call(-1,2) + func = lib.get('add_integers', ['int', 'int'], 'int') + assert 0 == func.call(0,0) + + func = lib.get('max3', ['int', 'int', 'int'], 'int') + assert 8 == func.call(2, 8, 3) + + func = lib.get('add_floats', ['float', 'float'], 'float') + assert 2.7 == func.call(1.2, 1.5) + + def test_get_void(self): + import jitffi + lib = jitffi.CDLL(self.lib_name) + + func = lib.get('fvoid', [], 'int') + assert 1 == func.call() + + func = lib.get('return_void', ['int', 'int'], 'void') + assert func.call(1, 2) is None + func = lib.get('return_void', ['int', 'int']) + assert func.call(1, 2) is None + + def test_undefined_func(self): + import jitffi + lib = jitffi.CDLL(self.lib_name) + # xxxfoo888baryyy - not existed function + py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', []) + py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') From getxsick at codespeak.net Fri Jun 18 01:57:43 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 18 Jun 2010 01:57:43 +0200 (CEST) Subject: [pypy-svn] r75443 - in pypy/branch/fast-ctypes/pypy: module/jitffi rlib Message-ID: <20100617235743.83002282B9C@codespeak.net> Author: getxsick Date: Fri Jun 18 01:57:39 2010 New Revision: 75443 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: kill not rpythonic super() Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Fri Jun 18 01:57:39 2010 @@ -7,7 +7,7 @@ class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - super(W_CDLL, self).__init__(name) + self._init(name) def get_w(self, func, w_args_type, res_type='void'): args_type_w = [ self.space.str_w(w_x) Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Fri Jun 18 01:57:39 2010 @@ -8,6 +8,9 @@ class CDLL(object): def __init__(self, name): + self._init(name) + + def _init(self, name): try: self.lib = rdynload.dlopen(name) except rdynload.DLOpenError, e: From antocuni at codespeak.net Fri Jun 18 10:57:07 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Jun 2010 10:57:07 +0200 (CEST) Subject: [pypy-svn] r75444 - pypy/branch/sys-prefix/pypy Message-ID: <20100618085707.37CF1282B9C@codespeak.net> Author: antocuni Date: Fri Jun 18 10:57:04 2010 New Revision: 75444 Modified: pypy/branch/sys-prefix/pypy/conftest.py Log: lib/py has been moved to ...../lib_pypy/py, but we can safely remove it as py does not contains tests nowadays Modified: pypy/branch/sys-prefix/pypy/conftest.py ============================================================================== --- pypy/branch/sys-prefix/pypy/conftest.py (original) +++ pypy/branch/sys-prefix/pypy/conftest.py Fri Jun 18 10:57:04 2010 @@ -13,8 +13,6 @@ rsyncdirs = ['.', '../lib', '../demo'] rsyncignore = ['_cache'] -collect_ignore = ['./lib/py'] - # PyPy's command line extra options (these are added # to py.test's standard options) # From getxsick at codespeak.net Fri Jun 18 12:42:15 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 18 Jun 2010 12:42:15 +0200 (CEST) Subject: [pypy-svn] r75445 - in pypy/branch/fast-ctypes/pypy: module/jitffi rlib Message-ID: <20100618104215.AC5C2282B9C@codespeak.net> Author: getxsick Date: Fri Jun 18 12:42:14 2010 New Revision: 75445 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: better r75443 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Fri Jun 18 12:42:14 2010 @@ -7,7 +7,7 @@ class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - self._init(name) + rjitffi.CDLL.__init__(self, name) def get_w(self, func, w_args_type, res_type='void'): args_type_w = [ self.space.str_w(w_x) Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Fri Jun 18 12:42:14 2010 @@ -8,9 +8,6 @@ class CDLL(object): def __init__(self, name): - self._init(name) - - def _init(self, name): try: self.lib = rdynload.dlopen(name) except rdynload.DLOpenError, e: From antocuni at codespeak.net Fri Jun 18 13:21:07 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Jun 2010 13:21:07 +0200 (CEST) Subject: [pypy-svn] r75446 - in pypy/branch/sys-prefix: lib/pypy1.2/lib-python lib/pypy1.2/lib_pypy/distributed lib/pypy1.2/lib_pypy/distributed/test lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests pypy pypy/module/test_lib_pypy/ctypes_tests pypy/module/test_lib_pypy/test_distributed Message-ID: <20100618112107.75F64282B9C@codespeak.net> Author: antocuni Date: Fri Jun 18 13:21:05 2010 New Revision: 75446 Added: pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/distributed/README.tests pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/ - copied from r75431, pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests/ pypy/branch/sys-prefix/pypy/module/test_lib_pypy/test_distributed/ - copied from r75431, pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/distributed/test/ Removed: pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/distributed/test/ pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests/ Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/conftest.py pypy/branch/sys-prefix/pypy/conftest.py pypy/branch/sys-prefix/pypy/test_all.py Log: move distributed/test and ctypes_test into module/test_lib_pypy, as they are meant to be run at applevel Modified: pypy/branch/sys-prefix/lib/pypy1.2/lib-python/conftest.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/conftest.py (original) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib-python/conftest.py Fri Jun 18 13:21:05 2010 @@ -20,8 +20,8 @@ regrtestdir, modregrtestdir, testresultdir pytest_plugins = "resultlog", -rsyncdirs = ['.', '../pypy'] - +rsyncdirs = ['.', '../../../pypy/'] + # # Interfacing/Integrating with py.test's collection process # Added: pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/distributed/README.tests ============================================================================== --- (empty file) +++ pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/distributed/README.tests Fri Jun 18 13:21:05 2010 @@ -0,0 +1,2 @@ +Tests for distributed are app-level tests, so they are kept under +pypy/module/test_lib_pypy/ Modified: pypy/branch/sys-prefix/pypy/conftest.py ============================================================================== --- pypy/branch/sys-prefix/pypy/conftest.py (original) +++ pypy/branch/sys-prefix/pypy/conftest.py Fri Jun 18 13:21:05 2010 @@ -218,8 +218,10 @@ def accept_regular_test(self): if option.runappdirect: - # only collect regular tests if we are in an 'app_test' directory - return "app_test" in self.listnames() + # only collect regular tests if we are in an 'app_test' directory, + # or in test_lib_pypy + names = self.listnames() + return "app_test" in names or "test_lib_pypy" in names else: return True @@ -230,7 +232,7 @@ return True return False - def classnamefilter(self, name): + def classnamefilter(self, name): if name.startswith('Test'): return self.accept_regular_test() if name.startswith('AppTest'): Modified: pypy/branch/sys-prefix/pypy/test_all.py ============================================================================== --- pypy/branch/sys-prefix/pypy/test_all.py (original) +++ pypy/branch/sys-prefix/pypy/test_all.py Fri Jun 18 13:21:05 2010 @@ -13,9 +13,12 @@ However, now lib-python is under lib/pypy1.2/lib-python. We cannot just change buildbot, as it would break all the other current branches, so instead we replace lib-python with the correct path here. + + Note: instead of passing lib/pypy1.2/lib-python, but pass lib/pyyp1.2/ as + an argument: this way, the tests under lib_pypy are also run. """ import sys - from pypy.tool.lib_pypy import LIB_PYTHON + from pypy.tool.lib_pypy import LIB_ROOT if sys.argv and sys.argv[-1].endswith('lib-python'): libpython = py.path.local(sys.argv[-1]) if libpython.check(dir=True): @@ -24,7 +27,7 @@ return else: # patch it with the correct path - sys.argv[-1] = str(LIB_PYTHON) + sys.argv[-1] = str(LIB_ROOT) if __name__ == '__main__': From fijal at codespeak.net Fri Jun 18 20:14:53 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:14:53 +0200 (CEST) Subject: [pypy-svn] r75447 - pypy/build/bot2/pypybuildbot Message-ID: <20100618181453.64737282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:14:50 2010 New Revision: 75447 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Try to call package.py directly, avoiding pack.py alltogether Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:14:50 2010 @@ -50,9 +50,9 @@ kw['timeout'] = 3600 ShellCmd.__init__(self, workdir, *a, **kw) self.addFactoryArguments(**add_args) - self.command = (self.command + translationArgs + - [self.translationTarget] + targetArgs) - #self.command = ['cp', '/tmp/pypy-c', '.'] + #self.command = (self.command + translationArgs + + # [self.translationTarget] + targetArgs) + self.command = ['cp', '/tmp/pypy-c', '.'] # ________________________________________________________________ @@ -137,10 +137,6 @@ "--resultlog=pypyjit.log", "pypy/module/pypyjit/test"], logfiles={'pytestLog': 'pypyjit.log'})) - self.addStep(ShellCmd( - description="compress pypy-c", - command=["python", "pack.py"], - workdir='build/pypy/tool/release')) if pypyjit: kind = 'jit' else: @@ -148,12 +144,17 @@ kind = 'stackless' else: kind = 'nojit' + name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + self.addStep(ShellCmd( + description="compress pypy-c", + command=["python", "pypy/tool/release/package.py", + ".", WithProperties(name)], + workdir='build')) nightly = '~/nightly/' - name = 'pypy-c-' + kind + '-%(got_revision)s-' + platform + '.tar.bz2' - pypy_c_rel = 'build/pypy/translator/goal/pypy-c.tar.bz2' + pypy_c_rel = "build/" + name + ".tar.bz2" self.addStep(PyPyUpload(slavesrc=pypy_c_rel, masterdest=WithProperties(nightly), - basename=name, + basename=name + ".tar.bz2", workdir='.', blocksize=100*1024)) From fijal at codespeak.net Fri Jun 18 20:19:12 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:19:12 +0200 (CEST) Subject: [pypy-svn] r75448 - pypy/build/bot2/pypybuildbot Message-ID: <20100618181912.CBEF4282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:19:11 2010 New Revision: 75448 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Comment out for debugging Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:19:11 2010 @@ -106,37 +106,37 @@ self.addStep(Translate(translationArgs, targetArgs)) - if app_tests: - if app_tests == True: - app_tests = [] - self.addStep(ShellCmd( - description="app-level (-A) test", - command=["python", "testrunner/runner.py", - "--logfile=pytest-A.log", - "--config=pypy/pytest-A.cfg", - "--root=pypy", "--timeout=1800" - ] + ["--config=%s" % cfg for cfg in app_tests], - logfiles={'pytestLog': 'pytest-A.log'}, - timeout = 4000, - env={"PYTHONPATH": ['.']})) - - if lib_python: - self.addStep(ShellCmd( - description="lib-python test", - command=["python", "pypy/test_all.py", - "--pypy=pypy/translator/goal/pypy-c", - "--resultlog=cpython.log", "lib-python"], - logfiles={'pytestLog': 'cpython.log'})) - - if pypyjit: - # upload nightly build, if we're running jit tests - self.addStep(ShellCmd( - description="pypyjit tests", - command=["python", "pypy/test_all.py", - "--pypy=pypy/translator/goal/pypy-c", - "--resultlog=pypyjit.log", - "pypy/module/pypyjit/test"], - logfiles={'pytestLog': 'pypyjit.log'})) + # if app_tests: + # if app_tests == True: + # app_tests = [] + # self.addStep(ShellCmd( + # description="app-level (-A) test", + # command=["python", "testrunner/runner.py", + # "--logfile=pytest-A.log", + # "--config=pypy/pytest-A.cfg", + # "--root=pypy", "--timeout=1800" + # ] + ["--config=%s" % cfg for cfg in app_tests], + # logfiles={'pytestLog': 'pytest-A.log'}, + # timeout = 4000, + # env={"PYTHONPATH": ['.']})) + + # if lib_python: + # self.addStep(ShellCmd( + # description="lib-python test", + # command=["python", "pypy/test_all.py", + # "--pypy=pypy/translator/goal/pypy-c", + # "--resultlog=cpython.log", "lib-python"], + # logfiles={'pytestLog': 'cpython.log'})) + + # if pypyjit: + # # upload nightly build, if we're running jit tests + # self.addStep(ShellCmd( + # description="pypyjit tests", + # command=["python", "pypy/test_all.py", + # "--pypy=pypy/translator/goal/pypy-c", + # "--resultlog=pypyjit.log", + # "pypy/module/pypyjit/test"], + # logfiles={'pytestLog': 'pypyjit.log'})) if pypyjit: kind = 'jit' else: From fijal at codespeak.net Fri Jun 18 20:21:37 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:21:37 +0200 (CEST) Subject: [pypy-svn] r75449 - pypy/build/bot2/pypybuildbot Message-ID: <20100618182137.62D25282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:21:35 2010 New Revision: 75449 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Ooops Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:21:35 2010 @@ -152,7 +152,7 @@ workdir='build')) nightly = '~/nightly/' pypy_c_rel = "build/" + name + ".tar.bz2" - self.addStep(PyPyUpload(slavesrc=pypy_c_rel, + self.addStep(PyPyUpload(slavesrc=WithProperties(pypy_c_rel), masterdest=WithProperties(nightly), basename=name + ".tar.bz2", workdir='.', From fijal at codespeak.net Fri Jun 18 20:28:54 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:28:54 +0200 (CEST) Subject: [pypy-svn] r75450 - pypy/trunk/pypy/tool/release Message-ID: <20100618182854.1A3A7282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:28:53 2010 New Revision: 75450 Modified: pypy/trunk/pypy/tool/release/package.py Log: Add a posibility to copy to given directory Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Fri Jun 18 20:28:53 2010 @@ -32,7 +32,7 @@ pass def package(basedir, name='pypy-nightly', rename_pypy_c='pypy-c', - override_pypy_c = None): + copy_to_dir = None, override_pypy_c = None): basedir = py.path.local(basedir) if override_pypy_c is None: pypy_c = basedir.join('pypy', 'translator', 'goal', 'pypy-c') @@ -64,6 +64,9 @@ " " + name) finally: os.chdir(old_dir) + if copy_to_dir is not None: + print "Copying to %s" % copy_to_dir + shutil.copy(str(builddir.join(name + '.tar.bz2')), copy_to_dir) return builddir # for tests if __name__ == '__main__': From fijal at codespeak.net Fri Jun 18 20:29:06 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:29:06 +0200 (CEST) Subject: [pypy-svn] r75451 - pypy/build/bot2/pypybuildbot Message-ID: <20100618182906.B87EE282BDD@codespeak.net> Author: fijal Date: Fri Jun 18 20:29:05 2010 New Revision: 75451 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Update buildbot Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:29:05 2010 @@ -148,7 +148,8 @@ self.addStep(ShellCmd( description="compress pypy-c", command=["python", "pypy/tool/release/package.py", - ".", WithProperties(name)], + ".", WithProperties(name), 'pypy', + '.'], workdir='build')) nightly = '~/nightly/' pypy_c_rel = "build/" + name + ".tar.bz2" From fijal at codespeak.net Fri Jun 18 20:30:31 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:30:31 +0200 (CEST) Subject: [pypy-svn] r75452 - pypy/trunk/pypy/tool/release Message-ID: <20100618183031.AE1EC282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:30:30 2010 New Revision: 75452 Modified: pypy/trunk/pypy/tool/release/package.py Log: We can have more args these days Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Fri Jun 18 20:30:30 2010 @@ -70,7 +70,7 @@ return builddir # for tests if __name__ == '__main__': - if len(sys.argv) == 1 or len(sys.argv) > 4: + if len(sys.argv) == 1: print >>sys.stderr, __doc__ sys.exit(1) else: From fijal at codespeak.net Fri Jun 18 20:32:29 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:32:29 +0200 (CEST) Subject: [pypy-svn] r75453 - pypy/trunk/py/_process Message-ID: <20100618183229.BE002282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:32:28 2010 New Revision: 75453 Modified: pypy/trunk/py/_process/cmdexec.py Log: Grumble. sys.stdout.encoding can be None Modified: pypy/trunk/py/_process/cmdexec.py ============================================================================== --- pypy/trunk/py/_process/cmdexec.py (original) +++ pypy/trunk/py/_process/cmdexec.py Fri Jun 18 20:32:28 2010 @@ -18,8 +18,10 @@ universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.stdout.encoding) - err = py.builtin._totext(err, sys.stderr.encoding) + out = py.builtin._totext(out, sys.stdout.encoding or + sys.getdefaultencoding()) + err = py.builtin._totext(err, sys.stderr.encoding or + sys.getdefaultencoding()) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) From fijal at codespeak.net Fri Jun 18 20:37:52 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:37:52 +0200 (CEST) Subject: [pypy-svn] r75454 - pypy/build/bot2/pypybuildbot Message-ID: <20100618183752.4A73F282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:37:50 2010 New Revision: 75454 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Disable debugging Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:37:50 2010 @@ -50,9 +50,9 @@ kw['timeout'] = 3600 ShellCmd.__init__(self, workdir, *a, **kw) self.addFactoryArguments(**add_args) - #self.command = (self.command + translationArgs + - # [self.translationTarget] + targetArgs) - self.command = ['cp', '/tmp/pypy-c', '.'] + self.command = (self.command + translationArgs + + [self.translationTarget] + targetArgs) + #self.command = ['cp', '/tmp/pypy-c', '.'] # ________________________________________________________________ @@ -106,37 +106,37 @@ self.addStep(Translate(translationArgs, targetArgs)) - # if app_tests: - # if app_tests == True: - # app_tests = [] - # self.addStep(ShellCmd( - # description="app-level (-A) test", - # command=["python", "testrunner/runner.py", - # "--logfile=pytest-A.log", - # "--config=pypy/pytest-A.cfg", - # "--root=pypy", "--timeout=1800" - # ] + ["--config=%s" % cfg for cfg in app_tests], - # logfiles={'pytestLog': 'pytest-A.log'}, - # timeout = 4000, - # env={"PYTHONPATH": ['.']})) - - # if lib_python: - # self.addStep(ShellCmd( - # description="lib-python test", - # command=["python", "pypy/test_all.py", - # "--pypy=pypy/translator/goal/pypy-c", - # "--resultlog=cpython.log", "lib-python"], - # logfiles={'pytestLog': 'cpython.log'})) - - # if pypyjit: - # # upload nightly build, if we're running jit tests - # self.addStep(ShellCmd( - # description="pypyjit tests", - # command=["python", "pypy/test_all.py", - # "--pypy=pypy/translator/goal/pypy-c", - # "--resultlog=pypyjit.log", - # "pypy/module/pypyjit/test"], - # logfiles={'pytestLog': 'pypyjit.log'})) + if app_tests: + if app_tests == True: + app_tests = [] + self.addStep(ShellCmd( + description="app-level (-A) test", + command=["python", "testrunner/runner.py", + "--logfile=pytest-A.log", + "--config=pypy/pytest-A.cfg", + "--root=pypy", "--timeout=1800" + ] + ["--config=%s" % cfg for cfg in app_tests], + logfiles={'pytestLog': 'pytest-A.log'}, + timeout = 4000, + env={"PYTHONPATH": ['.']})) + + if lib_python: + self.addStep(ShellCmd( + description="lib-python test", + command=["python", "pypy/test_all.py", + "--pypy=pypy/translator/goal/pypy-c", + "--resultlog=cpython.log", "lib-python"], + logfiles={'pytestLog': 'cpython.log'})) + + if pypyjit: + upload nightly build, if we're running jit tests + self.addStep(ShellCmd( + description="pypyjit tests", + command=["python", "pypy/test_all.py", + "--pypy=pypy/translator/goal/pypy-c", + "--resultlog=pypyjit.log", + "pypy/module/pypyjit/test"], + logfiles={'pytestLog': 'pypyjit.log'})) if pypyjit: kind = 'jit' else: From fijal at codespeak.net Fri Jun 18 20:40:12 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:40:12 +0200 (CEST) Subject: [pypy-svn] r75455 - in pypy/trunk/pypy/tool/release: . test Message-ID: <20100618184012.105D3282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:40:11 2010 New Revision: 75455 Removed: pypy/trunk/pypy/tool/release/pack.py pypy/trunk/pypy/tool/release/test/test_pack.py Log: Remove pack.py alltogether, we don't need it anymore From jcreigh at codespeak.net Fri Jun 18 20:55:51 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Fri, 18 Jun 2010 20:55:51 +0200 (CEST) Subject: [pypy-svn] r75456 - in pypy/branch/x86-64-jit-backend: . dotviewer lib-python lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command lib-python/modified-2.5.2/distutils/tests py py/_cmdline py/_code py/_compat py/_io py/_log py/_path py/_path/gateway py/_plugin py/_process py/_test pypy/annotation pypy/annotation/test pypy/doc pypy/doc/play1 pypy/interpreter/test pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/llgraph/test pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/test pypy/jit/tl pypy/jit/tl/spli pypy/jit/tl/tinyframe pypy/jit/tl/tinyframe/test pypy/jit/tl/tla pypy/jit/tool pypy/jit/tool/test pypy/lib pypy/lib/app_test pypy/lib/app_test/ctypes_tests pypy/lib/test2 pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/_codecs pypy/module/_codecs/test pypy/module/_file/test pypy/module/_rawffi pypy/module/_rawffi/test pypy/module/bz2 pypy/module/bz2/test pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/patches pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/imp pypy/module/imp/test pypy/module/itertools/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/sys pypy/module/sys/test pypy/module/zipimport pypy/module/zipimport/test pypy/objspace pypy/objspace/flow pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/parsing/test pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory/gc pypy/rpython/memory/gctransform pypy/rpython/memory/gctransform/test pypy/rpython/memory/test pypy/rpython/numpy/test pypy/rpython/ootypesystem pypy/rpython/ootypesystem/test pypy/rpython/test pypy/rpython/tool pypy/tool pypy/tool/algo pypy/tool/algo/test pypy/tool/pytest pypy/tool/pytest/test pypy/tool/release pypy/tool/test pypy/translator pypy/translator/backendopt pypy/translator/backendopt/test pypy/translator/benchmark pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/platform pypy/translator/platform/test pypy/translator/tool pypy/translator/tool/test Message-ID: <20100618185551.6D9C2282B9C@codespeak.net> Author: jcreigh Date: Fri Jun 18 20:55:39 2010 New Revision: 75456 Added: pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py - copied unchanged from r75442, pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py pypy/branch/x86-64-jit-backend/pypy/doc/release-1.3.0.txt - copied unchanged from r75442, pypy/trunk/pypy/doc/release-1.3.0.txt pypy/branch/x86-64-jit-backend/pypy/jit/codewriter/ (props changed) - copied from r75442, pypy/trunk/pypy/jit/codewriter/ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/blackhole.py - copied unchanged from r75442, pypy/trunk/pypy/jit/metainterp/blackhole.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/jitexc.py - copied unchanged from r75442, pypy/trunk/pypy/jit/metainterp/jitexc.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_immutable.py - copied unchanged from r75442, pypy/trunk/pypy/jit/metainterp/test/test_immutable.py pypy/branch/x86-64-jit-backend/pypy/lib/test2/test_dbm_extra.py - copied unchanged from r75442, pypy/trunk/pypy/lib/test2/test_dbm_extra.py pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/largetest.bz2 - copied unchanged from r75442, pypy/trunk/pypy/module/bz2/test/largetest.bz2 pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/test_large.py - copied unchanged from r75442, pypy/trunk/pypy/module/bz2/test/test_large.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/cdatetime.py - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/cdatetime.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/modsupport.inl - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/include/modsupport.inl pypy/branch/x86-64-jit-backend/pypy/module/cpyext/patches/boost.patch - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/patches/boost.patch pypy/branch/x86-64-jit-backend/pypy/module/cpyext/patches/cx_Oracle.patch - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/comparisons.c - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/test/comparisons.c pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_translate.py - copied unchanged from r75442, pypy/trunk/pypy/module/cpyext/test/test_translate.py pypy/branch/x86-64-jit-backend/pypy/rlib/rdynload.py - copied unchanged from r75442, pypy/trunk/pypy/rlib/rdynload.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rdynload.py - copied unchanged from r75442, pypy/trunk/pypy/rlib/test/test_rdynload.py pypy/branch/x86-64-jit-backend/pypy/tool/algo/color.py - copied unchanged from r75442, pypy/trunk/pypy/tool/algo/color.py pypy/branch/x86-64-jit-backend/pypy/tool/algo/test/test_color.py - copied unchanged from r75442, pypy/trunk/pypy/tool/algo/test/test_color.py pypy/branch/x86-64-jit-backend/pypy/tool/release/ - copied from r75442, pypy/trunk/pypy/tool/release/ pypy/branch/x86-64-jit-backend/pypy/tool/test/test_sourcetools.py - copied unchanged from r75442, pypy/trunk/pypy/tool/test/test_sourcetools.py Removed: pypy/branch/x86-64-jit-backend/pypy/doc/play1/ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/codewriter.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/dump.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/effectinfo.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/heaptracker.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/policy.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/support.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_codewriter.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_effectinfo.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_support.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/datetime.py pypy/branch/x86-64-jit-backend/pypy/tool/package.py pypy/branch/x86-64-jit-backend/pypy/tool/test/test_package.py Modified: pypy/branch/x86-64-jit-backend/ (props changed) pypy/branch/x86-64-jit-backend/dotviewer/graphparse.py pypy/branch/x86-64-jit-backend/lib-python/conftest.py pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/msvccompiler.py pypy/branch/x86-64-jit-backend/py/ (props changed) pypy/branch/x86-64-jit-backend/py/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/__metainfo.py (props changed) pypy/branch/x86-64-jit-backend/py/_builtin.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/ (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pycleanup.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pyconvert_unittest.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pycountloc.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pylookup.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pysvnwcrevert.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pytest.py (props changed) pypy/branch/x86-64-jit-backend/py/_cmdline/pywhich.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/ (props changed) pypy/branch/x86-64-jit-backend/py/_code/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/_assertionnew.py (contents, props changed) pypy/branch/x86-64-jit-backend/py/_code/_assertionold.py (contents, props changed) pypy/branch/x86-64-jit-backend/py/_code/assertion.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/code.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/oldmagic.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/oldmagic2.py (props changed) pypy/branch/x86-64-jit-backend/py/_code/source.py (contents, props changed) pypy/branch/x86-64-jit-backend/py/_compat/ (props changed) pypy/branch/x86-64-jit-backend/py/_compat/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_compat/dep_doctest.py (props changed) pypy/branch/x86-64-jit-backend/py/_compat/dep_optparse.py (props changed) pypy/branch/x86-64-jit-backend/py/_compat/dep_subprocess.py (props changed) pypy/branch/x86-64-jit-backend/py/_compat/dep_textwrap.py (props changed) pypy/branch/x86-64-jit-backend/py/_error.py (props changed) pypy/branch/x86-64-jit-backend/py/_io/ (props changed) pypy/branch/x86-64-jit-backend/py/_io/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_io/capture.py (props changed) pypy/branch/x86-64-jit-backend/py/_io/saferepr.py (props changed) pypy/branch/x86-64-jit-backend/py/_io/terminalwriter.py (props changed) pypy/branch/x86-64-jit-backend/py/_log/ (props changed) pypy/branch/x86-64-jit-backend/py/_log/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_log/log.py (props changed) pypy/branch/x86-64-jit-backend/py/_log/warning.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/ (props changed) pypy/branch/x86-64-jit-backend/py/_path/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/cacheutil.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/common.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/gateway/ (props changed) pypy/branch/x86-64-jit-backend/py/_path/gateway/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/gateway/channeltest.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/gateway/channeltest2.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/gateway/remotepath.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/local.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/svnurl.py (props changed) pypy/branch/x86-64-jit-backend/py/_path/svnwc.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/ (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/hookspec.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest__pytest.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_assertion.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_capture.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_default.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_doctest.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_genscript.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_helpconfig.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_hooklog.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_junitxml.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_mark.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_monkeypatch.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_nose.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_pastebin.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_pdb.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_pylint.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_pytester.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_recwarn.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_restdoc.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_resultlog.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_runner.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_skipping.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_terminal.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_tmpdir.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/pytest_unittest.py (props changed) pypy/branch/x86-64-jit-backend/py/_plugin/standalonetemplate.py (props changed) pypy/branch/x86-64-jit-backend/py/_process/ (props changed) pypy/branch/x86-64-jit-backend/py/_process/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_process/cmdexec.py (contents, props changed) pypy/branch/x86-64-jit-backend/py/_process/forkedfunc.py (props changed) pypy/branch/x86-64-jit-backend/py/_process/killproc.py (props changed) pypy/branch/x86-64-jit-backend/py/_std.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/ (props changed) pypy/branch/x86-64-jit-backend/py/_test/__init__.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/cmdline.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/collect.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/config.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/conftesthandle.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/funcargs.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/parseopt.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/pluginmanager.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/pycollect.py (props changed) pypy/branch/x86-64-jit-backend/py/_test/session.py (props changed) pypy/branch/x86-64-jit-backend/py/_xmlgen.py (props changed) pypy/branch/x86-64-jit-backend/py/apipkg.py (props changed) pypy/branch/x86-64-jit-backend/pypy/annotation/binaryop.py pypy/branch/x86-64-jit-backend/pypy/annotation/builtin.py pypy/branch/x86-64-jit-backend/pypy/annotation/description.py pypy/branch/x86-64-jit-backend/pypy/annotation/test/test_annrpython.py pypy/branch/x86-64-jit-backend/pypy/annotation/unaryop.py pypy/branch/x86-64-jit-backend/pypy/doc/how-to-release.txt pypy/branch/x86-64-jit-backend/pypy/doc/objspace.txt pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_function.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/llimpl.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/descr.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/gc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/llmodel.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_descr.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_gc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/model.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_ll_random.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_random.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/support.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_send.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py pypy/branch/x86-64-jit-backend/pypy/jit/codewriter/test/ (props changed) pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/compile.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/executor.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/history.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/jitprof.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/logger.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizefindnode.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeutil.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resoperation.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resume.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/simple_optimize.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/specnode.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/oparser.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_basic.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_blackhole.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_compile.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_exception.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_executor.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_history.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_jitprof.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_list.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizefindnode.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_pyjitpl.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_recursive.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_resume.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_send.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_slist.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_string.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tl.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tlc.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtual.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualref.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmstate.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_ztranslation.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/typesystem.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualizable.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualref.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmspot.py pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmstate.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/spli/interpreter.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/tinyframe/ (props changed) pypy/branch/x86-64-jit-backend/pypy/jit/tl/tinyframe/test/ (props changed) pypy/branch/x86-64-jit-backend/pypy/jit/tl/tl.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/targettla.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/tla.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlc.py pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlr.py pypy/branch/x86-64-jit-backend/pypy/jit/tool/jitoutput.py pypy/branch/x86-64-jit-backend/pypy/jit/tool/test/test_jitoutput.py pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_functions.py pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_unicode.py pypy/branch/x86-64-jit-backend/pypy/lib/app_test/test_functools.py pypy/branch/x86-64-jit-backend/pypy/lib/dbm.py pypy/branch/x86-64-jit-backend/pypy/lib/test2/test_stackless.py pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/functional.py pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_classobj.py pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_functional.py pypy/branch/x86-64-jit-backend/pypy/module/_codecs/app_codecs.py pypy/branch/x86-64-jit-backend/pypy/module/_codecs/interp_codecs.py pypy/branch/x86-64-jit-backend/pypy/module/_codecs/test/test_codecs.py pypy/branch/x86-64-jit-backend/pypy/module/_file/test/test_file_extra.py pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/array.py pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/structure.py pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/test/test__rawffi.py pypy/branch/x86-64-jit-backend/pypy/module/bz2/interp_bz2.py pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/test_bz2_compdecomp.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/TODO pypy/branch/x86-64-jit-backend/pypy/module/cpyext/__init__.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/api.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/Python.h pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/datetime.h pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/object.h pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/stringobject.h pypy/branch/x86-64-jit-backend/pypy/module/cpyext/listobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/methodobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/modsupport.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/object.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/patches/mysqldb.patch (props changed) pypy/branch/x86-64-jit-backend/pypy/module/cpyext/patches/numpy.patch (props changed) pypy/branch/x86-64-jit-backend/pypy/module/cpyext/patches/pycairo.patch (props changed) pypy/branch/x86-64-jit-backend/pypy/module/cpyext/pyobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sequence.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sliceobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/slotdefs.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/src/stringobject.c pypy/branch/x86-64-jit-backend/pypy/module/cpyext/state.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stringobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stubs.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/foo.c pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cell.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cpyext.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_datetime.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_longobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_object.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sequence.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sliceobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_typeobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_unicodeobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/typeobject.py pypy/branch/x86-64-jit-backend/pypy/module/cpyext/unicodeobject.py pypy/branch/x86-64-jit-backend/pypy/module/imp/importing.py pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_app.py pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_import.py pypy/branch/x86-64-jit-backend/pypy/module/itertools/test/test_itertools.py pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/policy.py pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/test/test_pypy_c.py pypy/branch/x86-64-jit-backend/pypy/module/sys/__init__.py pypy/branch/x86-64-jit-backend/pypy/module/sys/app.py pypy/branch/x86-64-jit-backend/pypy/module/sys/interp_encoding.py pypy/branch/x86-64-jit-backend/pypy/module/sys/test/test_sysmodule.py pypy/branch/x86-64-jit-backend/pypy/module/zipimport/interp_zipimport.py pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_undocumented.py pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_zipimport.py pypy/branch/x86-64-jit-backend/pypy/objspace/descroperation.py pypy/branch/x86-64-jit-backend/pypy/objspace/flow/model.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/dictmultiobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/dicttype.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/formatting.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/frame.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/settype.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/stringobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_floatobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_stringformat.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_strutil.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_tupleobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_typeobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_unicodeobject.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/transparent.py pypy/branch/x86-64-jit-backend/pypy/objspace/std/unicodetype.py pypy/branch/x86-64-jit-backend/pypy/rlib/jit.py pypy/branch/x86-64-jit-backend/pypy/rlib/libffi.py pypy/branch/x86-64-jit-backend/pypy/rlib/parsing/test/test_regexparse.py pypy/branch/x86-64-jit-backend/pypy/rlib/rarithmetic.py pypy/branch/x86-64-jit-backend/pypy/rlib/rgc.py pypy/branch/x86-64-jit-backend/pypy/rlib/runicode.py pypy/branch/x86-64-jit-backend/pypy/rlib/rwin32.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_libffi.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rarithmetic.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rbigint.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rlocale.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rmmap.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rpoll.py pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_runicode.py pypy/branch/x86-64-jit-backend/pypy/rpython/llinterp.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llarena.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llmemory.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lloperation.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lltype.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/opimpl.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rclass.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rffi.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rlist.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/generation.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/marksweep.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_boehm.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/branch/x86-64-jit-backend/pypy/rpython/memory/test/test_lldict.py pypy/branch/x86-64-jit-backend/pypy/rpython/normalizecalls.py pypy/branch/x86-64-jit-backend/pypy/rpython/numpy/test/test_array.py pypy/branch/x86-64-jit-backend/pypy/rpython/ootypesystem/ootype.py pypy/branch/x86-64-jit-backend/pypy/rpython/ootypesystem/rlist.py pypy/branch/x86-64-jit-backend/pypy/rpython/ootypesystem/rootype.py pypy/branch/x86-64-jit-backend/pypy/rpython/ootypesystem/test/test_oolist.py pypy/branch/x86-64-jit-backend/pypy/rpython/raddress.py pypy/branch/x86-64-jit-backend/pypy/rpython/rbuiltin.py pypy/branch/x86-64-jit-backend/pypy/rpython/rmodel.py pypy/branch/x86-64-jit-backend/pypy/rpython/rrange.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_exception.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_llann.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_llinterp.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rdict.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rfloat.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rint.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rlist.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rptr.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rrange.py pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rvirtualizable2.py pypy/branch/x86-64-jit-backend/pypy/rpython/tool/rffi_platform.py pypy/branch/x86-64-jit-backend/pypy/tool/gcc_cache.py pypy/branch/x86-64-jit-backend/pypy/tool/pytest/appsupport.py pypy/branch/x86-64-jit-backend/pypy/tool/pytest/test/test_appsupport.py pypy/branch/x86-64-jit-backend/pypy/tool/runsubprocess.py pypy/branch/x86-64-jit-backend/pypy/tool/sourcetools.py pypy/branch/x86-64-jit-backend/pypy/tool/test/test_runsubprocess.py pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/storesink.py pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/test/test_storesink.py pypy/branch/x86-64-jit-backend/pypy/translator/benchmark/benchmarks.py pypy/branch/x86-64-jit-backend/pypy/translator/c/funcgen.py pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/test/test_asmgcroot.py pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/trackgcroot.py pypy/branch/x86-64-jit-backend/pypy/translator/c/genc.py pypy/branch/x86-64-jit-backend/pypy/translator/c/primitive.py pypy/branch/x86-64-jit-backend/pypy/translator/c/src/address.h pypy/branch/x86-64-jit-backend/pypy/translator/c/src/commondefs.h pypy/branch/x86-64-jit-backend/pypy/translator/c/src/int.h pypy/branch/x86-64-jit-backend/pypy/translator/c/src/mem.h pypy/branch/x86-64-jit-backend/pypy/translator/c/src/stack.h pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_extfunc.py pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_genc.py pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_lladdresses.py pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_refcount.py pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_standalone.py pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_typed.py pypy/branch/x86-64-jit-backend/pypy/translator/driver.py pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpreimportedpypy.py pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpypystandalone.py pypy/branch/x86-64-jit-backend/pypy/translator/platform/__init__.py pypy/branch/x86-64-jit-backend/pypy/translator/platform/darwin.py pypy/branch/x86-64-jit-backend/pypy/translator/platform/posix.py pypy/branch/x86-64-jit-backend/pypy/translator/platform/test/test_platform.py pypy/branch/x86-64-jit-backend/pypy/translator/platform/windows.py pypy/branch/x86-64-jit-backend/pypy/translator/tool/cbuild.py pypy/branch/x86-64-jit-backend/pypy/translator/tool/make_dot.py pypy/branch/x86-64-jit-backend/pypy/translator/tool/test/test_cbuild.py pypy/branch/x86-64-jit-backend/pypy/translator/translator.py Log: merged changes from trunk through r75441 Modified: pypy/branch/x86-64-jit-backend/dotviewer/graphparse.py ============================================================================== --- pypy/branch/x86-64-jit-backend/dotviewer/graphparse.py (original) +++ pypy/branch/x86-64-jit-backend/dotviewer/graphparse.py Fri Jun 18 20:55:39 2010 @@ -47,7 +47,8 @@ else: cmdline = 'neato -Tplain' #print >> sys.stderr, '* running:', cmdline - p = subprocess.Popen(cmdline, shell=True, close_fds=True, + close_fds = sys.platform != 'win32' + p = subprocess.Popen(cmdline, shell=True, close_fds=close_fds, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (child_in, child_out) = (p.stdin, p.stdout) try: Modified: pypy/branch/x86-64-jit-backend/lib-python/conftest.py ============================================================================== --- pypy/branch/x86-64-jit-backend/lib-python/conftest.py (original) +++ pypy/branch/x86-64-jit-backend/lib-python/conftest.py Fri Jun 18 20:55:39 2010 @@ -520,11 +520,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -532,7 +535,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): Modified: pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/command/build_ext.py Fri Jun 18 20:55:39 2010 @@ -647,7 +647,9 @@ """ # The python library is always needed on Windows. if sys.platform == "win32": - pythonlib = 'libpypy-c.exe' + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] Modified: pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/msvccompiler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/msvccompiler.py (original) +++ pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/distutils/msvccompiler.py Fri Jun 18 20:55:39 2010 @@ -159,14 +159,60 @@ s = s.replace(k, v) return s +def get_manifests(): + """Retrieves the manifest(s) embedded in the current executable""" + import ctypes.wintypes + EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA + EnumResourceNameCallback = ctypes.WINFUNCTYPE( + ctypes.wintypes.BOOL, + ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, + ctypes.wintypes.LONG, ctypes.wintypes.LONG) + FindResource = ctypes.windll.kernel32.FindResourceA + LoadResource = ctypes.windll.kernel32.LoadResource + FreeResource = ctypes.windll.kernel32.FreeResource + SizeofResource = ctypes.windll.kernel32.SizeofResource + LockResource = ctypes.windll.kernel32.LockResource + UnlockResource = lambda x: None # hehe + + manifests = [] + + def callback(hModule, lpType, lpName, lParam): + hResource = FindResource(hModule, lpName, lpType) + size = SizeofResource(hModule, hResource) + hData = LoadResource(hModule, hResource) + try: + ptr = LockResource(hData) + try: + manifests.append(ctypes.string_at(ptr, size)) + finally: + UnlockResource(hData) + finally: + FreeResource(hData) + return True + + hModule = None # main executable + RT_MANIFEST = 24 # from WinUser.h + EnumResourceNames(hModule, RT_MANIFEST, + EnumResourceNameCallback(callback), None) + return manifests + def get_build_version(): """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. """ + try: + manifests = get_manifests() + for manifest in manifests: + match = re.search('"Microsoft.VC([0-9]+).CRT"', manifest) + if match: + return int(match.group(1)) / 10.0 + except BaseException: + pass + # No manifest embedded, use default compiler version return 9.0 +def get_build_architecture(): + return 'Intel' + def normalize_and_reduce_paths(paths): """Return a list of normalized paths with duplicates removed. Modified: pypy/branch/x86-64-jit-backend/py/_code/_assertionnew.py ============================================================================== --- pypy/branch/x86-64-jit-backend/py/_code/_assertionnew.py (original) +++ pypy/branch/x86-64-jit-backend/py/_code/_assertionnew.py Fri Jun 18 20:55:39 2010 @@ -92,6 +92,7 @@ ast.LtE : "<=", ast.Gt : ">", ast.GtE : ">=", + ast.Pow : "**", ast.Is : "is", ast.IsNot : "is not", ast.In : "in", Modified: pypy/branch/x86-64-jit-backend/py/_code/_assertionold.py ============================================================================== --- pypy/branch/x86-64-jit-backend/py/_code/_assertionold.py (original) +++ pypy/branch/x86-64-jit-backend/py/_code/_assertionold.py Fri Jun 18 20:55:39 2010 @@ -138,28 +138,28 @@ __view__ = ast.Name def is_local(self, frame): - co = compile('%r in locals() is not globals()' % self.name, '?', 'eval') + source = '%r in locals() is not globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_global(self, frame): - co = compile('%r in globals()' % self.name, '?', 'eval') + source = '%r in globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_builtin(self, frame): - co = compile('%r not in locals() and %r not in globals()' % ( - self.name, self.name), '?', 'eval') + source = '%r not in locals() and %r not in globals()' % ( + self.name, self.name) try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: @@ -185,11 +185,11 @@ expr2.eval(frame) self.explanation = "%s %s %s" % ( expr.explanation, operation, expr2.explanation) - co = compile("__exprinfo_left %s __exprinfo_right" % operation, - '?', 'eval') + source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(co, __exprinfo_left=expr.result, - __exprinfo_right=expr2.result) + self.result = frame.eval(source, + __exprinfo_left=expr.result, + __exprinfo_right=expr2.result) except passthroughex: raise except: @@ -235,14 +235,14 @@ class UnaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): expr = Interpretable(self.expr) expr.eval(frame) self.explanation = astpattern.replace('__exprinfo_expr', expr.explanation) try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(astpattern, + __exprinfo_expr=expr.result) except passthroughex: raise except: @@ -263,8 +263,7 @@ class BinaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): left = Interpretable(self.left) left.eval(frame) right = Interpretable(self.right) @@ -273,8 +272,9 @@ .replace('__exprinfo_left', left .explanation) .replace('__exprinfo_right', right.explanation)) try: - self.result = frame.eval(co, __exprinfo_left=left.result, - __exprinfo_right=right.result) + self.result = frame.eval(astpattern, + __exprinfo_left=left.result, + __exprinfo_right=right.result) except passthroughex: raise except: @@ -287,9 +287,10 @@ __view__ = ast.CallFunc def is_bool(self, frame): - co = compile('isinstance(__exprinfo_value, bool)', '?', 'eval') + source = 'isinstance(__exprinfo_value, bool)' try: - return frame.is_true(frame.eval(co, __exprinfo_value=self.result)) + return frame.is_true(frame.eval(source, + __exprinfo_value=self.result)) except passthroughex: raise except: @@ -336,9 +337,8 @@ if source.endswith(','): source = source[:-1] source += ')' - co = compile(source, '?', 'eval') try: - self.result = frame.eval(co, **vars) + self.result = frame.eval(source, **vars) except passthroughex: raise except: @@ -353,21 +353,20 @@ def eval(self, frame): expr = Interpretable(self.expr) expr.eval(frame) - co = compile('__exprinfo_expr.%s' % self.attrname, '?', 'eval') + source = '__exprinfo_expr.%s' % self.attrname try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(source, __exprinfo_expr=expr.result) except passthroughex: raise except: raise Failure(self) self.explanation = '%s.%s' % (expr.explanation, self.attrname) # if the attribute comes from the instance, its value is interesting - co = compile('hasattr(__exprinfo_expr, "__dict__") and ' - '%r in __exprinfo_expr.__dict__' % self.attrname, - '?', 'eval') + source = ('hasattr(__exprinfo_expr, "__dict__") and ' + '%r in __exprinfo_expr.__dict__' % self.attrname) try: from_instance = frame.is_true( - frame.eval(co, __exprinfo_expr=expr.result)) + frame.eval(source, __exprinfo_expr=expr.result)) except passthroughex: raise except: Modified: pypy/branch/x86-64-jit-backend/py/_code/source.py ============================================================================== --- pypy/branch/x86-64-jit-backend/py/_code/source.py (original) +++ pypy/branch/x86-64-jit-backend/py/_code/source.py Fri Jun 18 20:55:39 2010 @@ -17,6 +17,7 @@ """ a immutable object holding a source code fragment, possibly deindenting it. """ + _compilecounter = 0 def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -195,10 +196,12 @@ if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno + base = "<%d-codegen " % self._compilecounter + self.__class__._compilecounter += 1 if not filename: - filename = '' % (fn, lineno) + filename = base + '%s:%d>' % (fn, lineno) else: - filename = '' % (filename, fn, lineno) + filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) Modified: pypy/branch/x86-64-jit-backend/py/_process/cmdexec.py ============================================================================== --- pypy/branch/x86-64-jit-backend/py/_process/cmdexec.py (original) +++ pypy/branch/x86-64-jit-backend/py/_process/cmdexec.py Fri Jun 18 20:55:39 2010 @@ -18,8 +18,8 @@ universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.getdefaultencoding()) - err = py.builtin._totext(err, sys.getdefaultencoding()) + out = py.builtin._totext(out, sys.stdout.encoding) + err = py.builtin._totext(err, sys.stderr.encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) Modified: pypy/branch/x86-64-jit-backend/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/annotation/binaryop.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/annotation/binaryop.py Fri Jun 18 20:55:39 2010 @@ -442,7 +442,7 @@ return SomeUnicodeString() class __extend__(pairtype(SomeString, SomeUnicodeString), - pairtype(SomeString, SomeUnicodeString)): + pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") Modified: pypy/branch/x86-64-jit-backend/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/annotation/builtin.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/annotation/builtin.py Fri Jun 18 20:55:39 2010 @@ -8,7 +8,7 @@ from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString from pypy.annotation.model import SomePBC, SomeInstance, SomeDict, SomeList -from pypy.annotation.model import SomeWeakRef +from pypy.annotation.model import SomeWeakRef, SomeIterator from pypy.annotation.model import SomeOOObject from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation from pypy.annotation.model import add_knowntypedata @@ -85,6 +85,9 @@ builtin_xrange = builtin_range # xxx for now allow it +def builtin_enumerate(s_obj): + return SomeIterator(s_obj, "enumerate") + def builtin_bool(s_obj): return s_obj.is_true() @@ -340,7 +343,7 @@ assert s_type.is_constant() return SomePtr(s_type.const) -def llmemory_cast_adr_to_int(s): +def llmemory_cast_adr_to_int(s, s_mode=None): return SomeInteger() # xxx def llmemory_cast_int_to_adr(s): Modified: pypy/branch/x86-64-jit-backend/pypy/annotation/description.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/annotation/description.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/annotation/description.py Fri Jun 18 20:55:39 2010 @@ -539,9 +539,18 @@ try: args.fixedunpack(0) except ValueError: - raise Exception("default __init__ takes no argument" " (class %s)" % (self.name,)) + elif self.pyobj is Exception: + # check explicitly against "raise Exception, x" where x + # is a low-level exception pointer + try: + [s_arg] = args.fixedunpack(1) + except ValueError: + pass + else: + from pypy.annotation.model import SomePtr + assert not isinstance(s_arg, SomePtr) else: # call the constructor args = args.prepend(s_instance) Modified: pypy/branch/x86-64-jit-backend/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/annotation/test/test_annrpython.py Fri Jun 18 20:55:39 2010 @@ -3321,6 +3321,28 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + # + def f(): + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise Exception, lle + # ^^^ instead, must cast back from a base ptr to an instance + a = self.RPythonAnnotator() + py.test.raises(AssertionError, a.build_types, f, []) + + def test_enumerate(self): + def f(): + for i, x in enumerate(['a', 'b', 'c', 'd']): + if i == 2: + return x + return '?' + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeChar) + + def g(n): return [0,1,2,n] Modified: pypy/branch/x86-64-jit-backend/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/annotation/unaryop.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/annotation/unaryop.py Fri Jun 18 20:55:39 2010 @@ -577,6 +577,9 @@ return can_throw def next(itr): + if itr.variant == ("enumerate",): + s_item = itr.s_container.getanyitem() + return SomeTuple((SomeInteger(nonneg=True), s_item)) return itr.s_container.getanyitem(*itr.variant) next.can_only_throw = _can_only_throw method_next = next Modified: pypy/branch/x86-64-jit-backend/pypy/doc/how-to-release.txt ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/doc/how-to-release.txt (original) +++ pypy/branch/x86-64-jit-backend/pypy/doc/how-to-release.txt Fri Jun 18 20:55:39 2010 @@ -4,12 +4,13 @@ Overview --------- -As a meta rule setting up issues in the tracker for items here may help not forgetting things. -A set of todo files may also work. +As a meta rule setting up issues in the tracker for items here may help not +forgetting things. A set of todo files may also work. Check and prioritize all issues for the release, postpone some if necessary, -create new issues also as necessary. A meeting (or meetings) should be organized -to decide what things are priorities, should go in and work for the release. +create new issues also as necessary. A meeting (or meetings) should be +organized to decide what things are priorities, should go in and work for +the release. An important thing is to get the documentation into an up-to-date state! @@ -25,27 +26,21 @@ necessary * update pypy/doc/contributor.txt (and possibly LICENSE) * update README +* go to pypy/tool/release and run: + force-builds.py /release/ +* wait for builds to complete, make sure there are no failures +* run pypy/tool/release/make_release.py, this will build necessary binaries + and upload them to pypy.org + + Following binaries should be built, however, we need more buildbots: + JIT: windows, linux, os/x + no JIT: windows, linux, os/x + sandbox: linux, os/x + stackless: windows, linux, os/x + * write release announcement pypy/doc/release-x.y(.z).txt the release announcement should contain a direct link to the download page - (which is getting started). -* update pypy/doc/getting-started.txt links at the top - and release number references, make sure it is generally up-to-date -* use, after the necessary updates, pypy/tool/makerelease.py to - make the tarballs on codespeak; this generates html doc for the - tarballs too. Use:: - - makerelease -tag .z pypy-x.y.z - - to tag and produce final tarballs. Without the '-tag' this can - be used to make pre-release testing tarballs. -* nowadays we have an extensive set of nightly builds and test - runs. Is probably good to do some minimal testing of the tarballs, - especially to check that things work even outside a working copy or - if some stuff is missing. We have some support for running part of - our nightly tests on tarballs (see - http://codespeak.net/svn/user/pedronis/tarball-testing). -* write a news item for the release in pypy/doc/news.txt -* update http://codespeak.net/svn/pypy/dist and codespeak's - precomputed html files -* send announcements to pypy-dev, pypy-funding, python-list, +* update pypy.org (under extradoc/pypy.org), rebuild and commit +* post announcement on morepypy.blogspot.com +* send announcements to pypy-dev, python-list, python-announce, python-dev ... Modified: pypy/branch/x86-64-jit-backend/pypy/doc/objspace.txt ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/doc/objspace.txt (original) +++ pypy/branch/x86-64-jit-backend/pypy/doc/objspace.txt Fri Jun 18 20:55:39 2010 @@ -552,7 +552,7 @@ A number of options for configuration is here in `traceconfig.py`_. -.. _`found here` : getting-started.html#tracing-bytecode-and-operations-on-objects +.. _`found here` : getting-started-dev.html#tracing-bytecode-and-operations-on-objects .. _`Abstract Interpretation`: theory.html#abstract-interpretation .. _`traceconfig.py`: ../tool/traceconfig.py Modified: pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_function.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_function.py Fri Jun 18 20:55:39 2010 @@ -158,13 +158,6 @@ assert res[0] == 42 assert res[1] == {'something': 23} - def test_kwargs_sets_positional_mixed(self): - def func(arg1, **kw): - return arg1, kw - res = func(arg1=42, something=23) - assert res[0] == 42 - assert res[1] == {'something': 23} - def test_kwargs_sets_positional_twice(self): def func(arg1, **kw): return arg1, kw Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/llimpl.py Fri Jun 18 20:55:39 2010 @@ -4,12 +4,12 @@ when executing on top of the llinterpreter. """ -import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel -from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, +from pypy.jit.metainterp.history import (ConstInt, ConstPtr, BoxInt, BoxPtr, BoxObj, BoxFloat, REF, INT, FLOAT) +from pypy.jit.codewriter import heaptracker from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport @@ -73,12 +73,12 @@ 'int_eq' : (('int', 'int'), 'bool'), 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), + 'int_is_zero' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), - 'bool_not' : (('bool',), 'bool'), 'uint_add' : (('int', 'int'), 'int'), 'uint_sub' : (('int', 'int'), 'int'), 'uint_mul' : (('int', 'int'), 'int'), @@ -103,7 +103,6 @@ 'float_ge' : (('float', 'float'), 'bool'), 'float_neg' : (('float',), 'float'), 'float_abs' : (('float',), 'float'), - 'float_is_true' : (('float',), 'bool'), 'cast_float_to_int':(('float',), 'int'), 'cast_int_to_float':(('int',), 'float'), 'same_as' : (('int',), 'int'), # could also be ptr=>ptr @@ -127,7 +126,6 @@ 'arraylen_gc' : (('ref',), 'int'), 'call' : (('ref', 'varargs'), 'intorptr'), 'call_assembler' : (('ref', 'varargs'), 'intorptr'), - 'call_pure' : (('ref', 'varargs'), 'intorptr'), 'cond_call_gc_wb' : (('ptr', 'ptr'), None), 'oosend' : (('varargs',), 'intorptr'), 'oosend_pure' : (('varargs',), 'intorptr'), @@ -155,16 +153,6 @@ 'force_token' : ((), 'int'), 'call_may_force' : (('int', 'varargs'), 'intorptr'), 'guard_not_forced': ((), None), - 'virtual_ref' : (('ref', 'int'), 'ref'), - 'virtual_ref_finish': (('ref', 'ref'), None), - #'getitem' : (('void', 'ref', 'int'), 'int'), - #'setitem' : (('void', 'ref', 'int', 'int'), None), - #'newlist' : (('void', 'varargs'), 'ref'), - #'append' : (('void', 'ref', 'int'), None), - #'insert' : (('void', 'ref', 'int', 'int'), None), - #'pop' : (('void', 'ref',), 'int'), - #'len' : (('void', 'ref',), 'int'), - #'listnonzero' : (('void', 'ref',), 'int'), } # ____________________________________________________________ @@ -231,19 +219,19 @@ else: return repr(x) -def repr_list(lst, types, memocast): +def repr_list(lst, types): res_l = [] if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, memocast)) + res_l.append('(%s)' % repr1(elem, tp)) else: - res_l.append(repr1(elem, tp, memocast)) + res_l.append(repr1(elem, tp)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, memocast): +def repr1(x, tp): if tp == "intorptr": TYPE = lltype.typeOf(x) if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': @@ -259,7 +247,7 @@ return '(* None)' if isinstance(x, int): # XXX normalize? - ptr = str(cast_int_to_adr(memocast, x)) + ptr = str(llmemory.cast_int_to_adr(x)) elif isinstance(ootype.typeOf(x), ootype.OOType): return repr(x) else: @@ -400,10 +388,9 @@ class Frame(object): OPHANDLERS = [None] * (rop._LAST+1) - def __init__(self, memocast, cpu): + def __init__(self, cpu): self.verbose = False self.cpu = cpu - self.memocast = memocast self.opindex = 1 self._forced = False self._may_force = -1 @@ -522,15 +509,14 @@ elif res is NotImplemented: resdata = '*fail*' else: - resdata = '-> ' + repr1(res, restype, self.memocast) + resdata = '-> ' + repr1(res, restype) # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), + log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes), resdata)) return res def as_int(self, x): - return cast_to_int(x, self.memocast) + return cast_to_int(x) def as_ptr(self, x): return cast_to_ptr(x) @@ -554,34 +540,36 @@ try: op = getattr(cls, 'op_' + opname.lower()) # op_guard_true etc. except AttributeError: - name = 'do_' + opname.lower() try: - impl = globals()[name] # do_arraylen_gc etc. + impl = globals()['do_' + opname.lower()] # do_arraylen_gc etc. def op(self, descr, *args): - return impl(descr, *args) - # + if descr is None: + return impl(*args) + else: + return impl(descr, *args) except KeyError: - from pypy.jit.backend.llgraph import llimpl - impl = getattr(executor, name) # do_int_add etc. - def _op_default_implementation(self, descr, *args): - # for all operations implemented in execute.py - boxedargs = [] - for x in args: - if type(x) is int: - boxedargs.append(BoxInt(x)) - elif type(x) is float: - boxedargs.append(BoxFloat(x)) - elif isinstance(ootype.typeOf(x), ootype.OOType): - boxedargs.append(BoxObj(ootype.cast_to_object(x))) - else: - boxedargs.append(BoxPtr(x)) - # xxx this passes the 'llimpl' module as the CPU argument - resbox = impl(llimpl, *boxedargs) - return getattr(resbox, 'value', None) - op = _op_default_implementation - # + op = cls._make_impl_from_blackhole_interp(opname) cls.OPHANDLERS[opnum] = op + @classmethod + def _make_impl_from_blackhole_interp(cls, opname): + from pypy.jit.metainterp.blackhole import BlackholeInterpreter + name = 'bhimpl_' + opname.lower() + func = BlackholeInterpreter.__dict__[name] + for argtype in func.argtypes: + assert argtype in ('i', 'r', 'f') + # + def _op_default_implementation(self, descr, *args): + # for all operations implemented in the blackhole interpreter + return func(*args) + # + return _op_default_implementation + + def op_debug_merge_point(self, _, value): + from pypy.jit.metainterp.warmspot import get_stats + loc = ConstPtr(value)._get_str() + get_stats().add_merge_point_location(loc) + def op_guard_true(self, _, value): if not value: raise GuardFailed @@ -596,7 +584,7 @@ def op_guard_class(self, _, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_class), + llmemory.cast_int_to_adr(expected_class), rclass.CLASSTYPE) if value.typeptr != expected_class: raise GuardFailed @@ -630,7 +618,7 @@ def _cast_exception(self, exception): return llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, exception), + llmemory.cast_int_to_adr(exception), rclass.CLASSTYPE) def _issubclass(self, cls1, cls2): @@ -696,7 +684,7 @@ if arraydescr.typeinfo == REF: return do_getarrayitem_gc_ptr(array, index) elif arraydescr.typeinfo == INT: - return do_getarrayitem_gc_int(array, index, self.memocast) + return do_getarrayitem_gc_int(array, index) elif arraydescr.typeinfo == FLOAT: return do_getarrayitem_gc_float(array, index) else: @@ -708,7 +696,7 @@ if fielddescr.typeinfo == REF: return do_getfield_gc_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_gc_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: return do_getfield_gc_float(struct, fielddescr.ofs) else: @@ -718,11 +706,11 @@ def op_getfield_raw(self, fielddescr, struct): if fielddescr.typeinfo == REF: - return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: - return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_float(struct, fielddescr.ofs) else: raise NotImplementedError @@ -733,17 +721,17 @@ def op_new_with_vtable(self, descr, vtable): assert descr is None - size = get_class_size(self.memocast, vtable) - result = do_new(size) + descr = heaptracker.vtable2descr(self.cpu, vtable) + result = do_new(descr.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) - value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) + value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr.typeinfo == REF: do_setarrayitem_gc_ptr(array, index, newvalue) elif arraydescr.typeinfo == INT: - do_setarrayitem_gc_int(array, index, newvalue, self.memocast) + do_setarrayitem_gc_int(array, index, newvalue) elif arraydescr.typeinfo == FLOAT: do_setarrayitem_gc_float(array, index, newvalue) else: @@ -753,8 +741,7 @@ if fielddescr.typeinfo == REF: do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_gc_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: do_setfield_gc_float(struct, fielddescr.ofs, newvalue) else: @@ -762,32 +749,41 @@ def op_setfield_raw(self, fielddescr, struct, newvalue): if fielddescr.typeinfo == REF: - do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: - do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_float(struct, fielddescr.ofs, newvalue) else: raise NotImplementedError def op_call(self, calldescr, func, *args): - _call_args[:] = args - if calldescr.typeinfo == 'v': - err_result = None - elif calldescr.typeinfo == REF: - err_result = lltype.nullptr(llmemory.GCREF.TO) - elif calldescr.typeinfo == INT: - err_result = 0 - elif calldescr.typeinfo == FLOAT: - err_result = 0.0 - else: - raise NotImplementedError - return _do_call_common(func, self.memocast, err_result) - - op_call_pure = op_call + global _last_exception + assert _last_exception is None, "exception left behind" + assert _call_args_i == _call_args_r == _call_args_f == [] + args_in_order = [] + for x in args: + T = lltype.typeOf(x) + if T is lltype.Signed: + args_in_order.append('i') + _call_args_i.append(x) + elif T == llmemory.GCREF: + args_in_order.append('r') + _call_args_r.append(x) + elif T is lltype.Float: + args_in_order.append('f') + _call_args_f.append(x) + else: + raise TypeError(x) + try: + return _do_call_common(func, args_in_order) + except LLException, lle: + _last_exception = lle + d = {'v': None, + REF: lltype.nullptr(llmemory.GCREF.TO), + INT: 0, + FLOAT: 0.0} + return d[calldescr.typeinfo] def op_cond_call_gc_wb(self, descr, a, b): py.test.skip("cond_call_gc_wb not supported") @@ -801,7 +797,7 @@ return do_new_array(arraydescr.ofs, count) def op_cast_ptr_to_int(self, descr, ptr): - return cast_to_int(ptr, self.memocast) + return cast_to_int(ptr) def op_uint_xor(self, descr, arg1, arg2): return arg1 ^ arg2 @@ -859,12 +855,6 @@ if forced: raise GuardFailed - def op_virtual_ref(self, _, virtual, index): - return virtual - - def op_virtual_ref_finish(self, _, vref, virtual): - pass - class OOFrame(Frame): @@ -925,19 +915,17 @@ def op_call(self, calldescr, func, *args): sm = ootype.cast_from_object(calldescr.FUNC, func) - newargs = cast_call_args(calldescr.FUNC.ARGS, args, self.memocast) + newargs = cast_call_args(calldescr.FUNC.ARGS, args) res = call_maybe_on_top_of_llinterp(sm, newargs) if isinstance(calldescr.FUNC.RESULT, ootype.OOType): return ootype.cast_to_object(res) return res - op_call_pure = op_call - def op_oosend(self, descr, obj, *args): METH = descr.METH obj = ootype.cast_from_object(descr.SELFTYPE, obj) meth = getattr(obj, descr.methname) - newargs = cast_call_args(METH.ARGS, args, self.memocast) + newargs = cast_call_args(METH.ARGS, args) res = call_maybe_on_top_of_llinterp(meth, newargs) if isinstance(METH.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -973,27 +961,27 @@ # ____________________________________________________________ -def cast_to_int(x, memocast): +def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): - return cast_adr_to_int(memocast, llmemory.cast_ptr_to_adr(x)) + return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return cast_adr_to_int(memocast, x) + return heaptracker.adr2int(x) return lltype.cast_primitive(lltype.Signed, x) -def cast_from_int(TYPE, x, memocast): +def cast_from_int(TYPE, x): if isinstance(TYPE, lltype.Ptr): - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) elif TYPE == llmemory.Address: - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) assert lltype.typeOf(x) == llmemory.Address return x else: if lltype.typeOf(x) == llmemory.Address: - x = cast_adr_to_int(memocast, x) + x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x) def cast_to_ptr(x): @@ -1013,11 +1001,11 @@ return x -def new_frame(memocast, is_oo, cpu): +def new_frame(is_oo, cpu): if is_oo: - frame = OOFrame(memocast, cpu) + frame = OOFrame(cpu) else: - frame = Frame(memocast, cpu) + frame = Frame(cpu) return _to_opaque(frame) _future_values = [] @@ -1067,69 +1055,68 @@ def frame_int_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Signed + return x def frame_float_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Float + return x def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - result = frame.fail_args[num] - frame.fail_args[num] = None - return result + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) == llmemory.GCREF + return x -_last_exception = None +def frame_get_value_count(frame): + frame = _from_opaque(frame) + return len(frame.fail_args) -def get_exception(): - if _last_exception: - return llmemory.cast_ptr_to_adr(_last_exception.args[0]) - else: - return llmemory.NULL +def frame_clear_latest_values(frame, count): + frame = _from_opaque(frame) + assert count == len(frame.fail_args) + del frame.fail_args -def get_exc_value(): - if _last_exception: - return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) - else: - return lltype.nullptr(llmemory.GCREF.TO) +_last_exception = None -def clear_exception(): +def grab_exc_value(): global _last_exception - _last_exception = None + if _last_exception is not None: + result = _last_exception.args[1] + _last_exception = None + return lltype.cast_opaque_ptr(llmemory.GCREF, result) + else: + return lltype.nullptr(llmemory.GCREF.TO) -_pseudo_exceptions = {} +##_pseudo_exceptions = {} -def _get_error(Class): - if _llinterp.typer is not None: - llframe = _llinterp.frame_class(None, None, _llinterp) - try: - llframe.make_llexception(Class()) - except LLException, e: - return e - else: - assert 0, "should have raised" - else: - # for tests, a random emulated ll_inst will do - if Class not in _pseudo_exceptions: - ll_inst = lltype.malloc(rclass.OBJECT, zero=True) - ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, - immortal=True) - _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) - return _pseudo_exceptions[Class] - -def get_overflow_error(): - return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0]) - -def get_overflow_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(OverflowError).args[1]) - -def get_zero_division_error(): - return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0]) - -def get_zero_division_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(ZeroDivisionError).args[1]) +##def _get_error(Class): +## if _llinterp.typer is not None: +## llframe = _llinterp.frame_class(None, None, _llinterp) +## try: +## llframe.make_llexception(Class()) +## except LLException, e: +## return e +## else: +## assert 0, "should have raised" +## else: +## # for tests, a random emulated ll_inst will do +## if Class not in _pseudo_exceptions: +## ll_inst = lltype.malloc(rclass.OBJECT, zero=True) +## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, +## immortal=True) +## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) +## return _pseudo_exceptions[Class] + +##def get_overflow_error_value(): +## return lltype.cast_opaque_ptr(llmemory.GCREF, +## _get_error(OverflowError).args[1]) def force(opaque_frame): frame = _from_opaque(opaque_frame) @@ -1151,40 +1138,30 @@ def get_frame_forced_token(opaque_frame): return llmemory.cast_ptr_to_adr(opaque_frame) -class MemoCast(object): - def __init__(self): - self.addresses = [llmemory.NULL] - self.rev_cache = {} - self.vtable_to_size = {} - -def new_memo_cast(): - memocast = MemoCast() - return _to_opaque(memocast) - -def cast_adr_to_int(memocast, adr): - # xxx slow - assert lltype.typeOf(adr) == llmemory.Address - memocast = _from_opaque(memocast) - addresses = memocast.addresses - for i in xrange(len(addresses)-1, -1, -1): - if addresses[i] == adr: - return i - i = len(addresses) - addresses.append(adr) - return i - -def cast_int_to_adr(memocast, int): - memocast = _from_opaque(memocast) - assert 0 <= int < len(memocast.addresses) - return memocast.addresses[int] - -def get_class_size(memocast, vtable): - memocast = _from_opaque(memocast) - return memocast.vtable_to_size[vtable] - -def set_class_size(memocast, vtable, size): - memocast = _from_opaque(memocast) - memocast.vtable_to_size[vtable] = size +##def cast_adr_to_int(memocast, adr): +## # xxx slow +## assert lltype.typeOf(adr) == llmemory.Address +## memocast = _from_opaque(memocast) +## addresses = memocast.addresses +## for i in xrange(len(addresses)-1, -1, -1): +## if addresses[i] == adr: +## return i +## i = len(addresses) +## addresses.append(adr) +## return i + +##def cast_int_to_adr(memocast, int): +## memocast = _from_opaque(memocast) +## assert 0 <= int < len(memocast.addresses) +## return memocast.addresses[int] + +##def get_class_size(memocast, vtable): +## memocast = _from_opaque(memocast) +## return memocast.vtable_to_size[vtable] + +##def set_class_size(memocast, vtable, size): +## memocast = _from_opaque(memocast) +## memocast.vtable_to_size[vtable] = size class GuardFailed(Exception): pass @@ -1192,29 +1169,32 @@ # ____________________________________________________________ +def do_same_as(x): + return x + def do_arraylen_gc(arraydescr, array): array = array._obj.container return array.getlength() -def do_strlen(_, string): +def do_strlen(string): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return len(str.chars) -def do_strgetitem(_, string, index): +def do_strgetitem(string, index): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) -def do_unicodelen(_, string): +def do_unicodelen(string): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return len(uni.chars) -def do_unicodegetitem(_, string, index): +def do_unicodegetitem(string, index): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return ord(uni.chars[index]) -def do_getarrayitem_gc_int(array, index, memocast): +def do_getarrayitem_gc_int(array, index): array = array._obj.container - return cast_to_int(array.getitem(index), memocast) + return cast_to_int(array.getitem(index)) def do_getarrayitem_gc_float(array, index): array = array._obj.container @@ -1229,8 +1209,8 @@ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_gc_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_gc(struct, fieldnum), memocast) +def do_getfield_gc_int(struct, fieldnum): + return cast_to_int(_getfield_gc(struct, fieldnum)) def do_getfield_gc_float(struct, fieldnum): return cast_to_float(_getfield_gc(struct, fieldnum)) @@ -1238,19 +1218,19 @@ def do_getfield_gc_ptr(struct, fieldnum): return cast_to_ptr(_getfield_gc(struct, fieldnum)) -def _getfield_raw(struct, fieldnum, memocast): +def _getfield_raw(struct, fieldnum): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_raw_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast) +def do_getfield_raw_int(struct, fieldnum): + return cast_to_int(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_float(struct, fieldnum, memocast): - return cast_to_float(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_float(struct, fieldnum): + return cast_to_float(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_ptr(struct, fieldnum, memocast): - return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_ptr(struct, fieldnum): + return cast_to_ptr(_getfield_raw(struct, fieldnum)) def do_new(size): TYPE = symbolic.Size2Type[size] @@ -1262,10 +1242,10 @@ x = lltype.malloc(TYPE, count, zero=True) return cast_to_ptr(x) -def do_setarrayitem_gc_int(array, index, newvalue, memocast): +def do_setarrayitem_gc_int(array, index, newvalue): array = array._obj.container ITEMTYPE = lltype.typeOf(array).OF - newvalue = cast_from_int(ITEMTYPE, newvalue, memocast) + newvalue = cast_from_int(ITEMTYPE, newvalue) array.setitem(index, newvalue) def do_setarrayitem_gc_float(array, index, newvalue): @@ -1280,11 +1260,11 @@ newvalue = cast_from_ptr(ITEMTYPE, newvalue) array.setitem(index, newvalue) -def do_setfield_gc_int(struct, fieldnum, newvalue, memocast): +def do_setfield_gc_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) def do_setfield_gc_float(struct, fieldnum, newvalue): @@ -1301,108 +1281,129 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_int(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_float(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_float(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_float(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_ptr(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_newstr(_, length): +def do_newstr(length): x = rstr.mallocstr(length) return cast_to_ptr(x) -def do_newunicode(_, length): +def do_newunicode(length): return cast_to_ptr(rstr.mallocunicode(length)) -def do_strsetitem(_, string, index, newvalue): +def do_strsetitem(string, index, newvalue): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) -def do_unicodesetitem(_, string, index, newvalue): +def do_unicodesetitem(string, index, newvalue): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) uni.chars[index] = unichr(newvalue) # ---------- call ---------- -_call_args = [] +_call_args_i = [] +_call_args_r = [] +_call_args_f = [] def do_call_pushint(x): - _call_args.append(x) - -def do_call_pushfloat(x): - _call_args.append(x) + _call_args_i.append(x) def do_call_pushptr(x): - _call_args.append(x) + _call_args_r.append(x) -def _do_call_common(f, memocast, err_result=None): - global _last_exception - assert _last_exception is None, "exception left behind" - ptr = cast_int_to_adr(memocast, f).ptr +def do_call_pushfloat(x): + _call_args_f.append(x) + +def _do_call_common(f, args_in_order=None): + ptr = llmemory.cast_int_to_adr(f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS - args = cast_call_args(ARGS, _call_args, memocast) - del _call_args[:] + args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f, + args_in_order) + del _call_args_i[:] + del _call_args_r[:] + del _call_args_f[:] assert len(ARGS) == len(args) - try: - if hasattr(ptr._obj, 'graph'): - llinterp = _llinterp # it's a global set here by CPU.__init__() - result = llinterp.eval_graph(ptr._obj.graph, args) - else: - result = ptr._obj._callable(*args) - except LLException, e: - _last_exception = e - result = err_result + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() + result = llinterp.eval_graph(ptr._obj.graph, args) + # ^^^ may raise, in which case we get an LLException + else: + result = ptr._obj._callable(*args) return result -def do_call_void(f, memocast): - _do_call_common(f, memocast) +def do_call_void(f): + _do_call_common(f) -def do_call_int(f, memocast): - x = _do_call_common(f, memocast, 0) - return cast_to_int(x, memocast) +def do_call_int(f): + x = _do_call_common(f) + return cast_to_int(x) -def do_call_float(f, memocast): - x = _do_call_common(f, memocast, 0) +def do_call_float(f): + x = _do_call_common(f) return cast_to_float(x) -def do_call_ptr(f, memocast): - x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO)) +def do_call_ptr(f): + x = _do_call_common(f) return cast_to_ptr(x) -def cast_call_args(ARGS, args, memocast): - argsiter = iter(args) +def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None): + argsiter_i = iter(args_i) + argsiter_r = iter(args_r) + argsiter_f = iter(args_f) + if args_in_order is not None: + orderiter = iter(args_in_order) args = [] for TYPE in ARGS: if TYPE is lltype.Void: x = None else: - x = argsiter.next() if isinstance(TYPE, ootype.OOType): + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = ootype.cast_from_object(TYPE, x) elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = cast_from_ptr(TYPE, x) elif TYPE is lltype.Float: + if args_in_order is not None: + n = orderiter.next() + assert n == 'f' + x = argsiter_f.next() x = cast_from_float(TYPE, x) else: - x = cast_from_int(TYPE, x, memocast) + if args_in_order is not None: + n = orderiter.next() + assert n == 'i' + x = argsiter_i.next() + x = cast_from_int(TYPE, x) args.append(x) - assert list(argsiter) == [] + assert list(argsiter_i) == [] + assert list(argsiter_r) == [] + assert list(argsiter_f) == [] return args @@ -1421,7 +1422,7 @@ result = llinterp.eval_graph(mymethod.graph, myargs) else: result = meth(*args) - except LLException, e: + except XXX-LLException, e: _last_exception = e result = get_err_result_for_type(mymethod._TYPE.RESULT) return result @@ -1474,16 +1475,13 @@ COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame")) -MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[OOFrame] = OOFRAME.TO -_TO_OPAQUE[MemoCast] = MEMOCAST.TO s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) s_Frame = annmodel.SomePtr(FRAME) -s_MemoCast = annmodel.SomePtr(MEMOCAST) setannotation(compile_start, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) @@ -1512,23 +1510,14 @@ setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) setannotation(frame_float_getvalue, annmodel.SomeFloat()) +setannotation(frame_get_value_count, annmodel.SomeInteger()) +setannotation(frame_clear_latest_values, annmodel.s_None) -setannotation(get_exception, annmodel.SomeAddress()) -setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(clear_exception, annmodel.s_None) -setannotation(get_overflow_error, annmodel.SomeAddress()) -setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(get_zero_division_error, annmodel.SomeAddress()) -setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF)) setannotation(force, annmodel.SomeInteger()) setannotation(get_forced_token_frame, s_Frame) setannotation(get_frame_forced_token, annmodel.SomeAddress()) -setannotation(new_memo_cast, s_MemoCast) -setannotation(cast_adr_to_int, annmodel.SomeInteger()) -setannotation(cast_int_to_adr, annmodel.SomeAddress()) -setannotation(set_class_size, annmodel.s_None) - setannotation(do_arraylen_gc, annmodel.SomeInteger()) setannotation(do_strlen, annmodel.SomeInteger()) setannotation(do_strgetitem, annmodel.SomeInteger()) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/runner.py Fri Jun 18 20:55:39 2010 @@ -15,6 +15,7 @@ from pypy.jit.backend import model from pypy.jit.backend.llgraph import llimpl, symbolic from pypy.jit.metainterp.typesystem import llhelper, oohelper +from pypy.jit.codewriter import heaptracker from pypy.rlib import rgc class MiniStats: @@ -23,11 +24,19 @@ class Descr(history.AbstractDescr): - def __init__(self, ofs, typeinfo, extrainfo=None, name=None): + def __init__(self, ofs, typeinfo, extrainfo=None, name=None, + arg_types=None): self.ofs = ofs self.typeinfo = typeinfo self.extrainfo = extrainfo self.name = name + self.arg_types = arg_types + + def get_arg_types(self): + return self.arg_types + + def get_return_type(self): + return self.typeinfo def get_extra_info(self): return self.extrainfo @@ -51,6 +60,9 @@ def is_array_of_floats(self): return self.typeinfo == FLOAT + def as_vtable_size_descr(self): + return self + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -86,7 +98,6 @@ self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.stats.exec_conditional_jumps = 0 - self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._llinterp = LLInterpreter(self.rtyper) self._future_values = [] @@ -96,22 +107,16 @@ assert self.translate_support_code return False - def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None): - key = (ofs, typeinfo, extrainfo, name) + def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None, + arg_types=None): + key = (ofs, typeinfo, extrainfo, name, arg_types) try: return self._descrs[key] except KeyError: - descr = Descr(ofs, typeinfo, extrainfo, name) + descr = Descr(ofs, typeinfo, extrainfo, name, arg_types) self._descrs[key] = descr return descr - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - for vtable, size in class_sizes.items(): - if not self.is_oo: - size = size.ofs - llimpl.set_class_size(self.memo_cast, vtable, size) - def compile_bridge(self, faildescr, inputargs, operations): c = llimpl.compile_start() self._compile_loop_or_bridge(c, inputargs, operations) @@ -161,8 +166,6 @@ llimpl.compile_add_int_const(c, x.value) elif isinstance(x, self.ts.ConstRef): llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) elif isinstance(x, history.ConstFloat): llimpl.compile_add_float_const(c, x.value) else: @@ -213,7 +216,7 @@ def _execute_token(self, loop_token): compiled_version = loop_token._llgraph_compiled_version - frame = llimpl.new_frame(self.memo_cast, self.is_oo, self) + frame = llimpl.new_frame(self.is_oo, self) # setup the frame llimpl.frame_clear(frame, compiled_version) # run the loop @@ -247,60 +250,22 @@ def get_latest_value_float(self, index): return llimpl.frame_float_getvalue(self.latest_frame, index) + def get_latest_value_count(self): + return llimpl.frame_get_value_count(self.latest_frame) + def get_latest_force_token(self): token = llimpl.get_frame_forced_token(self.latest_frame) - return self.cast_adr_to_int(token) + return heaptracker.adr2int(token) - def make_boxes_from_latest_values(self, faildescr): - inputargs_and_holes = [] - for i in range(len(faildescr._fail_args_types)): - boxtype = faildescr._fail_args_types[i] - if boxtype == history.INT: - box = history.BoxInt(self.get_latest_value_int(i)) - elif boxtype == history.REF: - box = self.ts.BoxRef(self.get_latest_value_ref(i)) - elif boxtype == history.FLOAT: - box = history.BoxFloat(self.get_latest_value_float(i)) - elif boxtype == history.HOLE: - box = None - else: - assert False, "bad box type: num=%d" % ord(boxtype) - inputargs_and_holes.append(box) - return inputargs_and_holes + def clear_latest_values(self, count): + llimpl.frame_clear_latest_values(self.latest_frame, count) # ---------- - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) - - def get_exc_value(self): - return llimpl.get_exc_value() - - def clear_exception(self): - llimpl.clear_exception() - - def get_overflow_error(self): - return (self.cast_adr_to_int(llimpl.get_overflow_error()), - llimpl.get_overflow_error_value()) - - def get_zero_division_error(self): - return (self.cast_adr_to_int(llimpl.get_zero_division_error()), - llimpl.get_zero_division_error_value()) - def sizeof(self, S): assert not isinstance(S, lltype.Ptr) return self.getdescr(symbolic.get_size(S)) - def cast_adr_to_int(self, adr): - return llimpl.cast_adr_to_int(self.memo_cast, adr) - - def cast_int_to_adr(self, int): - return llimpl.cast_int_to_adr(self.memo_cast, int) - - def cast_gcref_to_int(self, gcref): - return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref)) - - class LLtypeCPU(BaseCPU): is_oo = False @@ -316,14 +281,17 @@ return self.getdescr(ofs, token[0], name=fieldname) def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): + arg_types = [] + for ARG in ARGS: + token = history.getkind(ARG) + if token != 'void': + arg_types.append(token[0]) token = history.getkind(RESULT) - return self.getdescr(0, token[0], extrainfo=extrainfo) - - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) + return self.getdescr(0, token[0], extrainfo=extrainfo, + arg_types=''.join(arg_types)) - def get_exc_value(self): - return llimpl.get_exc_value() + def grab_exc_value(self): + return llimpl.grab_exc_value() def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) @@ -334,202 +302,151 @@ # ---------- the backend-dependent operations ---------- - def do_arraylen_gc(self, arraybox, arraydescr): - array = arraybox.getref_base() - return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - - def do_strlen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_strlen(0, string)) - - def do_strgetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_strgetitem(0, string, index)) - - def do_unicodelen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_unicodelen(0, string)) - - def do_unicodegetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_unicodegetitem(0, string, index)) + def bh_strlen(self, string): + return llimpl.do_strlen(string) + + def bh_strgetitem(self, string, index): + return llimpl.do_strgetitem(string, index) + + def bh_unicodelen(self, string): + return llimpl.do_unicodelen(string) + + def bh_unicodegetitem(self, string, index): + return llimpl.do_unicodegetitem(string, index) - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) - elif arraydescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, - self.memo_cast)) - elif arraydescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array, - index)) - else: - raise NotImplementedError + return llimpl.do_getarrayitem_gc_int(array, index) + def bh_getarrayitem_gc_r(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_ptr(array, index) + def bh_getarrayitem_gc_f(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_float(array, index) - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_gc_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, - fielddescr.ofs)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_gc_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_gc_float(struct, - fielddescr.ofs)) - else: - raise NotImplementedError + return llimpl.do_getfield_gc_int(struct, fielddescr.ofs) + def bh_getfield_gc_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_ptr(struct, fielddescr.ofs) + def bh_getfield_gc_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_float(struct, fielddescr.ofs) - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_raw_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_raw_float(struct, - fielddescr.ofs, - self.memo_cast)) - else: - raise NotImplementedError + return llimpl.do_getfield_raw_int(struct, fielddescr.ofs) + def bh_getfield_raw_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_ptr(struct, fielddescr.ofs) + def bh_getfield_raw_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_float(struct, fielddescr.ofs) - def do_new(self, size): - assert isinstance(size, Descr) - return history.BoxPtr(llimpl.do_new(size.ofs)) - - def do_new_with_vtable(self, vtablebox): - vtable = vtablebox.getint() - size = self.class_sizes[vtable] - result = llimpl.do_new(size.ofs) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, - vtable, self.memo_cast) - return history.BoxPtr(result) - - def do_new_array(self, countbox, size): - assert isinstance(size, Descr) - count = countbox.getint() - return history.BoxPtr(llimpl.do_new_array(size.ofs, count)) + def bh_new(self, sizedescr): + assert isinstance(sizedescr, Descr) + return llimpl.do_new(sizedescr.ofs) + + def bh_new_with_vtable(self, sizedescr, vtable): + assert isinstance(sizedescr, Descr) + result = llimpl.do_new(sizedescr.ofs) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, vtable) + return result + + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_new_array(self, arraydescr, length): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) - elif arraydescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setarrayitem_gc_int(array, index, newvalue, - self.memo_cast) - elif arraydescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setarrayitem_gc_float(array, index, newvalue) - else: - raise NotImplementedError + return llimpl.do_new_array(arraydescr.ofs, length) + + def bh_arraylen_gc(self, arraydescr, array): + assert isinstance(arraydescr, Descr) + return llimpl.do_arraylen_gc(arraydescr, array) + + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_int(array, index, newvalue) + + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_float(array, index, newvalue) - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - else: - raise NotImplementedError + llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memo_cast) - else: - raise NotImplementedError + llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue) - def do_same_as(self, box1): - return box1.clonebox() + def bh_newstr(self, length): + return llimpl.do_newstr(length) - def do_newstr(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newstr(0, length)) - - def do_newunicode(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newunicode(0, length)) - - def do_strsetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_strsetitem(0, string, index, newvalue) - - def do_unicodesetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_unicodesetitem(0, string, index, newvalue) + def bh_newunicode(self, length): + return llimpl.do_newunicode(length) - def do_call(self, args, calldescr): - assert isinstance(calldescr, Descr) - func = args[0].getint() - for arg in args[1:]: - if arg.type == REF: - llimpl.do_call_pushptr(arg.getref_base()) - elif arg.type == FLOAT: - llimpl.do_call_pushfloat(arg.getfloat()) - else: - llimpl.do_call_pushint(arg.getint()) - if calldescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) - elif calldescr.typeinfo == INT: - return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) - elif calldescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast)) - elif calldescr.typeinfo == 'v': # void - llimpl.do_call_void(func, self.memo_cast) - else: - raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + llimpl.do_strsetitem(string, index, newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + llimpl.do_unicodesetitem(string, index, newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(INT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_int(func) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(REF, calldescr, args_i, args_r, args_f) + return llimpl.do_call_ptr(func) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(FLOAT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_float(func) + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call('v', calldescr, args_i, args_r, args_f) + llimpl.do_call_void(func) - def do_cast_ptr_to_int(self, ptrbox): - return history.BoxInt(llimpl.cast_to_int(ptrbox.getref_base(), - self.memo_cast)) + def _prepare_call(self, resulttypeinfo, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, Descr) + assert calldescr.typeinfo == resulttypeinfo + if args_i is not None: + for x in args_i: + llimpl.do_call_pushint(x) + if args_r is not None: + for x in args_r: + llimpl.do_call_pushptr(x) + if args_f is not None: + for x in args_f: + llimpl.do_call_pushfloat(x) def force(self, force_token): - token = self.cast_int_to_adr(force_token) + token = llmemory.cast_int_to_adr(force_token) frame = llimpl.get_forced_token_frame(token) fail_index = llimpl.force(frame) self.latest_frame = frame return self.get_fail_descr_from_number(fail_index) -class OOtypeCPU(BaseCPU): +class OOtypeCPU_xxx_disabled(BaseCPU): is_oo = True ts = oohelper @@ -629,7 +546,7 @@ assert isinstance(typedescr, TypeDescr) return typedescr.getarraylength(box1) - def do_call(self, args, descr): + def do_call_XXX(self, args, descr): assert isinstance(descr, StaticMethDescr) funcbox = args[0] argboxes = args[1:] @@ -842,10 +759,3 @@ def __repr__(self): return '' % self.fieldname - - -# ____________________________________________________________ - -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(LLtypeCPU) -pypy.jit.metainterp.executor.make_execute_list(OOtypeCPU) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Jun 18 20:55:39 2010 @@ -7,6 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.test.runner_test import LLtypeBackendTest class TestLLTypeLLGraph(LLtypeBackendTest): @@ -18,25 +19,25 @@ def setup_method(self, _): self.cpu = self.cpu_type(None) - def test_cast_adr_to_int_and_back(self): - cpu = self.cpu - X = lltype.Struct('X', ('foo', lltype.Signed)) - x = lltype.malloc(X, immortal=True) - x.foo = 42 - a = llmemory.cast_ptr_to_adr(x) - i = cpu.cast_adr_to_int(a) - assert isinstance(i, int) - a2 = cpu.cast_int_to_adr(i) - assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x - assert cpu.cast_adr_to_int(llmemory.NULL) == 0 - assert cpu.cast_int_to_adr(0) == llmemory.NULL +def test_cast_adr_to_int_and_back(): + X = lltype.Struct('X', ('foo', lltype.Signed)) + x = lltype.malloc(X, immortal=True) + x.foo = 42 + a = llmemory.cast_ptr_to_adr(x) + i = heaptracker.adr2int(a) + assert lltype.typeOf(i) is lltype.Signed + a2 = heaptracker.int2adr(i) + assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x + assert heaptracker.adr2int(llmemory.NULL) == 0 + assert heaptracker.int2adr(0) == llmemory.NULL ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type def test_fielddescr_ootype(): + py.test.skip("ootype tests skipped") from pypy.rpython.ootypesystem import ootype from pypy.jit.backend.llgraph.runner import OOtypeCPU A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/descr.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/descr.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/descr.py Fri Jun 18 20:55:39 2010 @@ -1,10 +1,11 @@ import py -from pypy.rpython.lltypesystem import lltype, rffi, llmemory +from pypy.rpython.lltypesystem import lltype, rffi, llmemory, rclass from pypy.jit.backend.llsupport import symbolic, support from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # The point of the class organization in this file is to make instances # as compact as possible. This is done by not storing the field size or @@ -40,6 +41,10 @@ def repr_of_descr(self): return '' % self.size +class SizeDescrWithVTable(SizeDescr): + def as_vtable_size_descr(self): + return self + BaseSizeDescr = SizeDescr def get_size_descr(gccache, STRUCT): @@ -48,7 +53,10 @@ return cache[STRUCT] except KeyError: size = symbolic.get_size(STRUCT, gccache.translate_support_code) - sizedescr = SizeDescr(size) + if heaptracker.has_gcstruct_a_vtable(STRUCT): + sizedescr = SizeDescrWithVTable(size) + else: + sizedescr = SizeDescr(size) gccache.init_size_descr(STRUCT, sizedescr) cache[STRUCT] = sizedescr return sizedescr @@ -179,7 +187,6 @@ # CallDescrs class BaseCallDescr(AbstractDescr): - empty_box = BoxInt(0) _clsname = '' loop_token = None arg_classes = '' # <-- annotation hack @@ -191,35 +198,20 @@ def get_extra_info(self): return self.extrainfo - _returns_a_pointer = False # unless overridden by GcPtrCallDescr - _returns_a_float = False # unless overridden by FloatCallDescr - _returns_a_void = False # unless overridden by VoidCallDescr - - def returns_a_pointer(self): - return self._returns_a_pointer - - def returns_a_float(self): - return self._returns_a_float + def get_arg_types(self): + return self.arg_classes - def returns_a_void(self): - return self._returns_a_void + def get_return_type(self): + return self._return_type def get_result_size(self, translate_support_code): raise NotImplementedError - def get_call_stub(self): - return self.call_stub - def create_call_stub(self, rtyper, RESULT): - def process(no, c): - if c == 'i': - return 'args[%d].getint()' % (no,) - elif c == 'f': - return 'args[%d].getfloat()' % (no,) - elif c == 'r': - return 'args[%d].getref_base()' % (no,) - else: - raise Exception("Unknown type %s for type %s" % (c, TP)) + def process(c): + arg = 'args_%s[%d]' % (c, seen[c]) + seen[c] += 1 + return arg def TYPE(arg): if arg == 'i': @@ -230,21 +222,23 @@ return llmemory.GCREF elif arg == 'v': return lltype.Void - - args = ", ".join([process(i + 1, c) for i, c in - enumerate(self.arg_classes)]) - - if self.returns_a_pointer(): - result = 'history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, res))' - elif self.returns_a_float(): - result = 'history.BoxFloat(res)' - elif self.returns_a_void(): + + seen = {'i': 0, 'r': 0, 'f': 0} + args = ", ".join([process(c) for c in self.arg_classes]) + + if self.get_return_type() == history.INT: + result = 'rffi.cast(lltype.Signed, res)' + elif self.get_return_type() == history.REF: + result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)' + elif self.get_return_type() == history.FLOAT: + result = 'res' + elif self.get_return_type() == history.VOID: result = 'None' else: - result = 'history.BoxInt(rffi.cast(lltype.Signed, res))' + assert 0 source = py.code.Source(""" - def call_stub(args): - fnptr = rffi.cast(lltype.Ptr(FUNC), args[0].getint()) + def call_stub(func, args_i, args_r, args_f): + fnptr = rffi.cast(lltype.Ptr(FUNC), func) res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s) return %(result)s """ % locals()) @@ -255,35 +249,64 @@ exec source.compile() in d self.call_stub = d['call_stub'] + def verify_types(self, args_i, args_r, args_f, return_type): + assert self._return_type == return_type + assert self.arg_classes.count('i') == len(args_i or ()) + assert self.arg_classes.count('r') == len(args_r or ()) + assert self.arg_classes.count('f') == len(args_f or ()) + def repr_of_descr(self): return '<%s>' % self._clsname -class NonGcPtrCallDescr(BaseCallDescr): +class BaseIntCallDescr(BaseCallDescr): + # Base class of the various subclasses of descrs corresponding to + # calls having a return kind of 'int' (including non-gc pointers). + # The inheritance hierarchy is a bit different than with other Descr + # classes because of the 'call_stub' attribute, which is of type + # + # lambda func, args_i, args_r, args_f --> int/ref/float/void + # + # The purpose of BaseIntCallDescr is to be the parent of all classes + # in which 'call_stub' has a return kind of 'int'. + _return_type = history.INT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0) + +class NonGcPtrCallDescr(BaseIntCallDescr): _clsname = 'NonGcPtrCallDescr' - def get_result_size(self, translate_support_code): return symbolic.get_size_of_ptr(translate_support_code) -class GcPtrCallDescr(NonGcPtrCallDescr): - empty_box = BoxPtr(lltype.nullptr(llmemory.GCREF.TO)) +class GcPtrCallDescr(BaseCallDescr): _clsname = 'GcPtrCallDescr' - _returns_a_pointer = True + _return_type = history.REF + call_stub = staticmethod(lambda func, args_i, args_r, args_f: + lltype.nullptr(llmemory.GCREF.TO)) + def get_result_size(self, translate_support_code): + return symbolic.get_size_of_ptr(translate_support_code) + +class FloatCallDescr(BaseCallDescr): + _clsname = 'FloatCallDescr' + _return_type = history.FLOAT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0.0) + def get_result_size(self, translate_support_code): + return symbolic.get_size(lltype.Float, translate_support_code) -class VoidCallDescr(NonGcPtrCallDescr): - empty_box = None +class VoidCallDescr(BaseCallDescr): _clsname = 'VoidCallDescr' - _returns_a_void = True - + _return_type = history.VOID + call_stub = staticmethod(lambda func, args_i, args_r, args_f: None) def get_result_size(self, translate_support_code): return 0 def getCallDescrClass(RESULT): if RESULT is lltype.Void: return VoidCallDescr - return getDescrClass(RESULT, BaseCallDescr, GcPtrCallDescr, + if RESULT is lltype.Float: + return FloatCallDescr + return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr, NonGcPtrCallDescr, 'Call', 'get_result_size', - '_returns_a_float') + Ellipsis) # <= floatattrname should not be used here def get_call_descr(gccache, ARGS, RESULT, extrainfo=None): arg_classes = [] @@ -330,7 +353,6 @@ # if TYPE is lltype.Float: setattr(Descr, floatattrname, True) - Descr.empty_box = BoxFloat(0.0) # _cache[nameprefix, TYPE] = Descr return Descr Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/gc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/gc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/gc.py Fri Jun 18 20:55:39 2010 @@ -170,7 +170,7 @@ # first look in the hashtable, using an inexact hash (fails after # the object moves) addr = llmemory.cast_ptr_to_adr(gcref) - hash = llmemory.cast_adr_to_int(addr) + hash = llmemory.cast_adr_to_int(addr, "forced") hash -= hash >> self.HASHTABLE_BITS hash &= self.HASHTABLE_SIZE - 1 addr_ref = self.hashtable[hash] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/llmodel.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/llmodel.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/llmodel.py Fri Jun 18 20:55:39 2010 @@ -6,16 +6,19 @@ from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\ BoxFloat +from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.model import AbstractCPU 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, BaseSizeDescr from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr -from pypy.jit.backend.llsupport.descr import get_call_descr, BaseCallDescr +from pypy.jit.backend.llsupport.descr import get_call_descr +from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr +from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr from pypy.rpython.annlowlevel import cast_instance_to_base_ptr -empty_int_box = BoxInt(0) class AbstractLLCPU(AbstractCPU): from pypy.jit.metainterp.typesystem import llhelper as ts @@ -47,7 +50,7 @@ self._setup_exception_handling_translated() else: self._setup_exception_handling_untranslated() - self.clear_exception() + self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) self.setup() if translate_support_code: self._setup_on_leave_jitted_translated() @@ -57,9 +60,6 @@ def setup(self): pass - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case bk = self.rtyper.annotator.bookkeeper @@ -104,12 +104,10 @@ def save_exception(): # copy from _exception_emulator to the real attributes on self - tp_i = _exception_emulator[0] - v_i = _exception_emulator[1] + v_i = _exception_emulator[1] _exception_emulator[0] = 0 _exception_emulator[1] = 0 - self.saved_exception = tp_i - self.saved_exc_value = self._cast_int_to_gcref(v_i) + self.saved_exc_value = rffi.cast(llmemory.GCREF, v_i) self.pos_exception = pos_exception self.pos_exc_value = pos_exc_value @@ -120,15 +118,14 @@ def pos_exception(): addr = llop.get_exception_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def save_exception(): addr = llop.get_exception_addr(llmemory.Address) - exception = rffi.cast(lltype.Signed, addr.address[0]) addr.address[0] = llmemory.NULL addr = llop.get_exc_value_addr(llmemory.Address) exc_value = rffi.cast(llmemory.GCREF, addr.address[0]) @@ -136,7 +133,6 @@ # from now on, the state is again consistent -- no more RPython # exception is set. The following code produces a write barrier # in the assignment to self.saved_exc_value, as needed. - self.saved_exception = exception self.saved_exc_value = exc_value self.pos_exception = pos_exception @@ -174,16 +170,10 @@ f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc) return rffi.cast(lltype.Signed, f) - def get_exception(self): - return self.saved_exception - - def get_exc_value(self): - return self.saved_exc_value - - def clear_exception(self): - self.saved_exception = 0 + def grab_exc_value(self): + exc = self.saved_exc_value self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) - + return exc # ------------------- helpers and descriptions -------------------- @@ -213,24 +203,30 @@ def unpack_fielddescr(self, fielddescr): assert isinstance(fielddescr, BaseFieldDescr) + return fielddescr.offset + unpack_fielddescr._always_inline_ = True + + def unpack_fielddescr_size(self, fielddescr): + assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset size = fielddescr.get_field_size(self.translate_support_code) - ptr = fielddescr.is_pointer_field() - float = fielddescr.is_float_field() - return ofs, size, ptr, float - unpack_fielddescr._always_inline_ = True + return ofs, size + unpack_fielddescr_size._always_inline_ = True def arraydescrof(self, A): return get_array_descr(self.gc_ll_descr, A) def unpack_arraydescr(self, arraydescr): assert isinstance(arraydescr, BaseArrayDescr) + return arraydescr.get_base_size(self.translate_support_code) + unpack_arraydescr._always_inline_ = True + + def unpack_arraydescr_size(self, arraydescr): + assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_base_size(self.translate_support_code) size = arraydescr.get_item_size(self.translate_support_code) - ptr = arraydescr.is_array_of_pointers() - float = arraydescr.is_array_of_floats() - return ofs, size, ptr, float - unpack_arraydescr._always_inline_ = True + return ofs, size + unpack_arraydescr_size._always_inline_ = True def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo) @@ -249,254 +245,222 @@ # ____________________________________________________________ - def do_arraylen_gc(self, arraybox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_ofs_length(self.translate_support_code) - gcref = arraybox.getref_base() - length = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] - return BoxInt(length) - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) + return rffi.cast(rffi.CArrayPtr(lltype.Signed), array)[ofs/WORD] + + def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex): + ofs, size = self.unpack_arraydescr_size(arraydescr) # --- start of GC unsafe code (no GC operation!) --- items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - pval = self._cast_int_to_gcref(items[itemindex]) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - fval = items[itemindex] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: items = rffi.cast(rffi.CArrayPtr(TYPE), items) val = items[itemindex] # --- end of GC unsafe code --- - return BoxInt(rffi.cast(lltype.Signed, val)) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_setarrayitem_gc(self, arraybox, indexbox, vbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) - # - if ptr: - vboxptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, vboxptr) - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - items[itemindex] = self.cast_gcref_to_int(vboxptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - items[itemindex] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def bh_getarrayitem_gc_r(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + pval = self._cast_int_to_gcref(items[itemindex]) + # --- end of GC unsafe code --- + return pval + + def bh_getarrayitem_gc_f(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + fval = items[itemindex] + # --- end of GC unsafe code --- + return fval + + def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue): + ofs, size = self.unpack_arraydescr_size(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) items = rffi.cast(rffi.CArrayPtr(TYPE), items) - items[itemindex] = rffi.cast(TYPE, val) + items[itemindex] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def _new_do_len(TP): - def do_strlen(self, stringbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(TP, - self.translate_support_code) - gcref = stringbox.getref_base() - v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] - return BoxInt(v) - return do_strlen - - do_strlen = _new_do_len(rstr.STR) - do_unicodelen = _new_do_len(rstr.UNICODE) - - def do_strgetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] - return BoxInt(ord(v)) - - def do_unicodegetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - basesize = basesize // itemsize - v = rffi.cast(rffi.CArrayPtr(lltype.UniChar), gcref)[basesize + i] - return BoxInt(ord(v)) + def bh_setarrayitem_gc_r(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + self.gc_ll_descr.do_write_barrier(gcref, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + items[itemindex] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- + + def bh_setarrayitem_gc_f(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + items[itemindex] = newvalue + # --- end of GC unsafe code --- + + def bh_strlen(self, string): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return len(s.chars) + + def bh_unicodelen(self, string): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return len(u.chars) + + def bh_strgetitem(self, string, index): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return ord(s.chars[index]) + + def bh_unicodegetitem(self, string, index): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return ord(u.chars[index]) @specialize.argtype(1) - def _base_do_getfield(self, gcref, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) + def _base_do_getfield_i(self, struct, fielddescr): + ofs, size = self.unpack_fielddescr_size(fielddescr) # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), field)[0] - pval = self._cast_int_to_gcref(pval) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - fval = rffi.cast(rffi.CArrayPtr(lltype.Float), field)[0] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - val = rffi.cast(rffi.CArrayPtr(TYPE), field)[0] + val = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)[0] # --- end of GC unsafe code --- - val = rffi.cast(lltype.Signed, val) - return BoxInt(val) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_getfield_gc(self, structbox, fielddescr): - gcref = structbox.getref_base() - return self._base_do_getfield(gcref, fielddescr) + @specialize.argtype(1) + def _base_do_getfield_r(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0] + pval = self._cast_int_to_gcref(pval) + # --- end of GC unsafe code --- + return pval - def do_getfield_raw(self, structbox, fielddescr): - return self._base_do_getfield(structbox.getint(), fielddescr) + @specialize.argtype(1) + def _base_do_getfield_f(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fval = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr)[0] + # --- end of GC unsafe code --- + return fval + + bh_getfield_gc_i = _base_do_getfield_i + bh_getfield_gc_r = _base_do_getfield_r + bh_getfield_gc_f = _base_do_getfield_f + bh_getfield_raw_i = _base_do_getfield_i + bh_getfield_raw_r = _base_do_getfield_r + bh_getfield_raw_f = _base_do_getfield_f @specialize.argtype(1) - def _base_do_setfield(self, gcref, vbox, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) - # - if ptr: - assert lltype.typeOf(gcref) is not lltype.Signed, ( - "can't handle write barriers for setfield_raw") - ptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, ptr) - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Signed), field) - field[0] = self.cast_gcref_to_int(ptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Float), field) - field[0] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def _base_do_setfield_i(self, struct, fielddescr, newvalue): + ofs, size = self.unpack_fielddescr_size(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(TYPE), field) - field[0] = rffi.cast(TYPE, val) + fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr) + fieldptr[0] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def do_setfield_gc(self, structbox, vbox, fielddescr): - gcref = structbox.getref_base() - self._base_do_setfield(gcref, vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_r(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + assert lltype.typeOf(struct) is not lltype.Signed, ( + "can't handle write barriers for setfield_raw") + self.gc_ll_descr.do_write_barrier(struct, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr) + fieldptr[0] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- - def do_setfield_raw(self, structbox, vbox, fielddescr): - self._base_do_setfield(structbox.getint(), vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_f(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr) + fieldptr[0] = newvalue + # --- end of GC unsafe code --- + + bh_setfield_gc_i = _base_do_setfield_i + bh_setfield_gc_r = _base_do_setfield_r + bh_setfield_gc_f = _base_do_setfield_f + bh_setfield_raw_i = _base_do_setfield_i + bh_setfield_raw_r = _base_do_setfield_r + bh_setfield_raw_f = _base_do_setfield_f - def do_new(self, sizedescr): - res = self.gc_ll_descr.gc_malloc(sizedescr) - return BoxPtr(res) + def bh_new(self, sizedescr): + return self.gc_ll_descr.gc_malloc(sizedescr) - def do_new_with_vtable(self, classbox): - classint = classbox.getint() - descrsize = self.class_sizes[classint] - res = self.gc_ll_descr.gc_malloc(descrsize) + def bh_new_with_vtable(self, sizedescr, vtable): + res = self.gc_ll_descr.gc_malloc(sizedescr) if self.vtable_offset is not None: as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res) - as_array[self.vtable_offset/WORD] = classint - return BoxPtr(res) + as_array[self.vtable_offset/WORD] = vtable + return res - def do_new_array(self, countbox, arraydescr): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem) - return BoxPtr(res) - - def do_newstr(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_str(num_elem) - return BoxPtr(res) - - def do_newunicode(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_unicode(num_elem) - return BoxPtr(res) - - def do_strsetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) - - def do_unicodesetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - basesize = basesize // itemsize - rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v) - - def do_call(self, args, calldescr): - assert isinstance(calldescr, BaseCallDescr) - assert len(args) == 1 + len(calldescr.arg_classes) + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) + + def bh_new_array(self, arraydescr, length): + return self.gc_ll_descr.gc_malloc_array(arraydescr, length) + + def bh_newstr(self, length): + return self.gc_ll_descr.gc_malloc_str(length) + + def bh_newunicode(self, length): + return self.gc_ll_descr.gc_malloc_unicode(length) + + def bh_strsetitem(self, string, index, newvalue): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + s.chars[index] = chr(newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + u.chars[index] = unichr(newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, BaseIntCallDescr) if not we_are_translated(): - assert (list(calldescr.arg_classes) == - [arg.type for arg in args[1:]]) - callstub = calldescr.get_call_stub() - try: - return callstub(args) - except Exception, e: - if not we_are_translated(): - if not type(e) is LLException: - raise - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - e.args[1]) - self.saved_exception = rffi.cast(lltype.Signed, e.args[0]) - else: - ptr = cast_instance_to_base_ptr(e) - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - ptr) - self.saved_exception = rffi.cast(lltype.Signed, ptr.typeptr) - return calldescr.empty_box - - def do_cast_ptr_to_int(self, ptrbox): - return BoxInt(self.cast_gcref_to_int(ptrbox.getref_base())) + calldescr.verify_types(args_i, args_r, args_f, history.INT) + return calldescr.call_stub(func, args_i, args_r, args_f) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, GcPtrCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.REF) + return calldescr.call_stub(func, args_i, args_r, args_f) -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, FloatCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.FLOAT) + return calldescr.call_stub(func, args_i, args_r, args_f) + + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, VoidCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.VOID) + return calldescr.call_stub(func, args_i, args_r, args_f) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_descr.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_descr.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_descr.py Fri Jun 18 20:55:39 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp import history def test_get_size_descr(): c0 = GcCache(False) @@ -145,33 +146,29 @@ c0 = GcCache(False) descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char) assert descr1.get_result_size(False) == rffi.sizeof(lltype.Char) - assert not descr1.returns_a_pointer() - assert not descr1.returns_a_float() + assert descr1.get_return_type() == history.INT assert descr1.arg_classes == "ii" - assert isinstance(descr1.empty_box, BoxInt) # T = lltype.GcStruct('T') descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T)) assert descr2.get_result_size(False) == rffi.sizeof(lltype.Ptr(T)) - assert descr2.returns_a_pointer() - assert not descr2.returns_a_float() + assert descr2.get_return_type() == history.REF assert descr2.arg_classes == "r" - assert isinstance(descr2.empty_box, BoxPtr) # U = lltype.GcStruct('U', ('x', lltype.Signed)) assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U)) # V = lltype.Struct('V', ('x', lltype.Signed)) - assert isinstance(get_call_descr(c0, [], lltype.Ptr(V)).empty_box, BoxInt) + assert (get_call_descr(c0, [], lltype.Ptr(V)).get_return_type() == + history.INT) # - assert get_call_descr(c0, [], lltype.Void).empty_box is None + assert (get_call_descr(c0, [], lltype.Void).get_return_type() == + history.VOID) # descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float) assert descr4.get_result_size(False) == rffi.sizeof(lltype.Float) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" - assert isinstance(descr4.empty_box, BoxFloat) def test_get_call_descr_translated(): c1 = GcCache(True) @@ -179,14 +176,12 @@ U = lltype.GcStruct('U', ('x', lltype.Signed)) descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U)) assert isinstance(descr3.get_result_size(True), Symbolic) - assert descr3.returns_a_pointer() - assert not descr3.returns_a_float() + assert descr3.get_return_type() == history.REF assert descr3.arg_classes == "r" # descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float) assert isinstance(descr4.get_result_size(True), Symbolic) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" def test_call_descr_extra_info(): @@ -245,12 +240,11 @@ def f(a, b): return 'c' - call_stub = descr1.get_call_stub() + call_stub = descr1.call_stub fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) - res = call_stub([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxInt(1), BoxInt(2)]) - assert res.getint() == ord('c') + res = call_stub(rffi.cast(lltype.Signed, fnptr), [1, 2], None, None) + assert res == ord('c') ARRAY = lltype.GcArray(lltype.Signed) ARGS = [lltype.Float, lltype.Ptr(ARRAY)] @@ -264,6 +258,6 @@ a = lltype.malloc(ARRAY, 3) opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a) a[0] = 1 - res = descr2.get_call_stub()([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxFloat(3.5), BoxPtr(opaquea)]) - assert res.getfloat() == 4.5 + res = descr2.call_stub(rffi.cast(lltype.Signed, fnptr), + [], [opaquea], [3.5]) + assert res == 4.5 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_gc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_gc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/llsupport/test/test_gc.py Fri Jun 18 20:55:39 2010 @@ -291,7 +291,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -303,7 +303,7 @@ assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) - assert operations[1].opnum == rop.OOIS + assert operations[1].opnum == rop.PTR_EQ assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result @@ -324,7 +324,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -336,7 +336,7 @@ finally: rgc.can_move = old_can_move assert len(operations) == 1 - assert operations[0].opnum == rop.OOIS + assert operations[0].opnum == rop.PTR_EQ assert operations[0].args == [v_random_box, ConstPtr(s_gcref)] assert operations[0].result == v_result # check that s_gcref gets added to the list anyway, to make sure Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/model.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/model.py Fri Jun 18 20:55:39 2010 @@ -3,10 +3,14 @@ class AbstractCPU(object): supports_floats = False + _got_exception = None # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] @@ -24,9 +28,6 @@ def get_fail_descr_from_number(self, n): return self.fail_descr_list[n] - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def setup_once(self): """Called once by the front-end when the program starts.""" pass @@ -87,30 +88,27 @@ or from 'args' if it was a FINISH). Returns a ptr or an obj.""" raise NotImplementedError + def get_latest_value_count(self): + """Return how many values are ready to be returned by + get_latest_value_xxx(). Only after a guard failure; not + necessarily correct after a FINISH.""" + raise NotImplementedError + def get_latest_force_token(self): """After a GUARD_NOT_FORCED fails, this function returns the same FORCE_TOKEN result as the one in the just-failed loop.""" raise NotImplementedError - def make_boxes_from_latest_value(self, faildescr): - """Build a list of Boxes (and None for holes) that contains - the current values, as would be returned by calls to - get_latest_value_xxx().""" - raise NotImplementedError - - def get_exception(self): - raise NotImplementedError - - def get_exc_value(self): - raise NotImplementedError - - def clear_exception(self): - raise NotImplementedError - - def get_overflow_error(self): + def clear_latest_values(self, count): + """Clear the latest values (at least the ref ones), so that + they no longer keep objects alive. 'count' is the number of + values -- normally get_latest_value_count().""" raise NotImplementedError - def get_zero_division_error(self): + def grab_exc_value(self): + """Return and clear the exception set by the latest execute_token(), + when it exits due to a failure of a GUARD_EXCEPTION or + GUARD_NO_EXCEPTION. (Returns a GCREF)""" # XXX remove me raise NotImplementedError @staticmethod @@ -118,10 +116,6 @@ raise NotImplementedError @staticmethod - def numof(S): - raise NotImplementedError - - @staticmethod def fielddescrof(S, fieldname): """Return the Descr corresponding to field 'fieldname' on the structure 'S'. It is important that this function (at least) @@ -157,101 +151,87 @@ # lltype specific operations # -------------------------- - - def do_arraylen_gc(self, arraybox, arraydescr): - raise NotImplementedError - def do_strlen(self, stringbox): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): raise NotImplementedError - - def do_strgetitem(self, stringbox, indexbox): + def bh_getarrayitem_gc_r(self, arraydescr, array, index): raise NotImplementedError - - def do_unicodelen(self, stringbox): + def bh_getarrayitem_gc_f(self, arraydescr, array, index): raise NotImplementedError - def do_unicodegetitem(self, stringbox, indexbox): + def bh_getfield_gc_i(self, struct, fielddescr): raise NotImplementedError - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getfield_gc_r(self, struct, fielddescr): + raise NotImplementedError + def bh_getfield_gc_f(self, struct, fielddescr): raise NotImplementedError - def do_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): - return self.do_call([fnptr, sourcebox, destbox, source_startbox, - dest_startbox, lengthbox], calldescr) - - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): raise NotImplementedError - - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_r(self, struct, fielddescr): raise NotImplementedError - - def do_new(self, sizedescr): + def bh_getfield_raw_f(self, struct, fielddescr): raise NotImplementedError - def do_new_with_vtable(self, classbox): + def bh_new(self, sizedescr): + raise NotImplementedError + def bh_new_with_vtable(self, sizedescr, vtable): raise NotImplementedError - - def do_new_array(self, lengthbox, arraydescr): + def bh_new_array(self, arraydescr, length): raise NotImplementedError - - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_newstr(self, length): + raise NotImplementedError + def bh_newunicode(self, length): raise NotImplementedError - def do_setarrayitem_raw(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): raise NotImplementedError - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_classof(self, struct): raise NotImplementedError - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newstr(self, lengthbox): + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newunicode(self, lengthbox): + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): raise NotImplementedError - def do_strsetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_unicodesetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call(self, args, calldescr): + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_assembler(self, args, token): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call_loopinvariant(self, args, calldescr): - return self.do_call(args, calldescr) - - def do_cond_call_gc_wb(self, args, calldescr): + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_cast_ptr_to_int(self, ptrbox): + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_may_force(self, args, calldescr): - return self.do_call(args, calldescr) - - def force(self, force_token): + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - # ootype specific operations - # -------------------------- - - def do_runtimenew(self, classbox): + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - def do_oosend(self, args, descr): + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + raise NotImplementedError + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - def do_instanceof(self, instancebox, typedescr): + def bh_strlen(self, string): + raise NotImplementedError + def bh_strgetitem(self, string, index): + raise NotImplementedError + def bh_unicodelen(self, string): + raise NotImplementedError + def bh_unicodegetitem(self, string, index): + raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + raise NotImplementedError + def bh_unicodesetitem(self, string, index, newvalue): raise NotImplementedError - def typedescr2classbox(self, descr): + def force(self, force_token): raise NotImplementedError Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/runner_test.py Fri Jun 18 20:55:39 2010 @@ -1,4 +1,3 @@ - import py, sys, random, os, struct, operator from pypy.jit.metainterp.history import (AbstractFailDescr, BasicFailDescr, @@ -9,13 +8,13 @@ ConstObj, BoxFloat, ConstFloat) from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.typesystem import deref +from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass from pypy.rpython.ootypesystem import ootype -from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.jit.metainterp.test.oparser import parse from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException -from pypy.jit.metainterp.test.oparser import parse +from pypy.jit.codewriter import heaptracker + class Runner(object): @@ -239,7 +238,7 @@ res = self.cpu.get_latest_value_int(0) assert res == 20 - def test_make_boxes_from_latest_values(self): + def test_get_latest_value_count(self): i0 = BoxInt() i1 = BoxInt() i2 = BoxInt() @@ -258,12 +257,12 @@ self.cpu.set_future_value_int(0, 2) fail = self.cpu.execute_token(looptoken) assert fail is faildescr1 - boxes = self.cpu.make_boxes_from_latest_values(faildescr1) - assert len(boxes) == 3 - assert boxes[0] is None - assert isinstance(boxes[1], BoxInt) - assert boxes[1].value == 10 - assert boxes[2] is None + + count = self.cpu.get_latest_value_count() + assert count == 3 + assert self.cpu.get_latest_value_int(1) == 10 + assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok + self.cpu.clear_latest_values(3) def test_finish(self): i0 = BoxInt() @@ -378,8 +377,8 @@ looptoken = LoopToken() self.cpu.compile_loop([v1, v2], ops, looptoken) for x, y, z in testcases: - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) fail = self.cpu.execute_token(looptoken) @@ -389,13 +388,13 @@ assert fail.identifier == 2 if z != boom: assert self.cpu.get_latest_value_int(0) == z - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_ovf_operations_reversed(self): self.test_ovf_operations(reversed=True) - def test_do_call(self): + def test_bh_call(self): cpu = self.cpu # def func(c): @@ -403,24 +402,21 @@ FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxInt(ord('A'))], - calldescr) - assert x.value == ord('B') + x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value, + calldescr, [ord('A')], None, None) + assert x == ord('B') if cpu.supports_floats: def func(f, i): - return float(i) + f + return f - float(i) FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed], lltype.Float)) func_ptr = llhelper(FPTR, func) FTP = deref(FPTR) calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxFloat(3.5), BoxInt(42)], - calldescr) - assert x.value == 42 + 3.5 + x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value, + calldescr, + [42], None, [3.5]) + assert x == 3.5 - 42 def test_call(self): @@ -633,31 +629,31 @@ def test_ooops(self): u1_box, U_box = self.alloc_instance(self.U) u2_box, U_box = self.alloc_instance(self.U) - r = self.execute_operation(rop.OOIS, [u1_box, - u1_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, + u1_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [u2_box, - u2_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, + u2_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [u1_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int') assert r.value == 1 # null_box = self.null_instance() - r = self.execute_operation(rop.OOIS, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, + null_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOIS, [u1_box, null_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [null_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, + null_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, null_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [null_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int') assert r.value == 1 def test_array_basic(self): @@ -790,10 +786,10 @@ assert r.value == 153 def test_do_unicode_basic(self): - u_box = self.cpu.do_newunicode(ConstInt(5)) - self.cpu.do_unicodesetitem(u_box, BoxInt(4), BoxInt(123)) - r = self.cpu.do_unicodegetitem(u_box, BoxInt(4)) - assert r.value == 123 + u = self.cpu.bh_newunicode(5) + self.cpu.bh_unicodesetitem(u, 4, 123) + r = self.cpu.bh_unicodegetitem(u, 4) + assert r == 123 def test_unicode_basic(self): u_box = self.alloc_unicode(u"hello\u1234") @@ -830,17 +826,10 @@ assert r.value == 5.5 def test_virtual_ref(self): - # if VIRTUAL_REF reaches the backend, it should just be a SAME_AS - u_box = self.alloc_unicode(u"hello\u1234") - r = self.execute_operation(rop.VIRTUAL_REF, [u_box, ConstInt(2)], - 'ref') - assert r.value == u_box.value + pass # VIRTUAL_REF must not reach the backend nowadays def test_virtual_ref_finish(self): - # if VIRTUAL_REF_FINISH reaches the backend, it is a no-op - self.execute_operation(rop.VIRTUAL_REF_FINISH, - [BoxInt(123), BoxInt(234)], - 'void') + pass # VIRTUAL_REF_FINISH must not reach the backend nowadays def test_jump(self): # this test generates small loops where the JUMP passes many @@ -1104,7 +1093,6 @@ operator.truediv, no_zero_divison yield nan_and_infinity, rop.FLOAT_NEG, operator.neg, all_cases_unary yield nan_and_infinity, rop.FLOAT_ABS, abs, all_cases_unary - yield nan_and_infinity, rop.FLOAT_IS_TRUE, bool, all_cases_unary yield nan_and_infinity, rop.FLOAT_LT, operator.lt, all_cases_binary yield nan_and_infinity, rop.FLOAT_LE, operator.le, all_cases_binary yield nan_and_infinity, rop.FLOAT_EQ, operator.eq, all_cases_binary @@ -1124,7 +1112,7 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): addr = llmemory.cast_ptr_to_adr(func_ptr) - return BoxInt(cpu.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) MY_VTABLE = rclass.OBJECT_VTABLE # for tests only @@ -1156,7 +1144,7 @@ elif T == self.U: t.parent.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) + T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr)) return t_box, T_box def null_instance(self): @@ -1185,23 +1173,26 @@ def test_casts(self): + py.test.skip("xxx fix or kill") from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') x = lltype.malloc(TP) x = lltype.cast_opaque_ptr(llmemory.GCREF, x) res = self.execute_operation(rop.CAST_PTR_TO_INT, [BoxPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) res = self.execute_operation(rop.CAST_PTR_TO_INT, [ConstPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) - r = self.execute_operation(rop.OOIS, [BoxInt(v), BoxInt(v)], 'int') + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) + r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [BoxInt(v), BoxInt(v)], 'int') + r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 0 lltype.free(x, flavor='raw') @@ -1228,7 +1219,7 @@ S = lltype.Struct('S', ('x', lltype.Signed)) s = lltype.malloc(S, flavor='raw') sa = llmemory.cast_ptr_to_adr(s) - s_box = BoxInt(self.cpu.cast_adr_to_int(sa)) + s_box = BoxInt(heaptracker.adr2int(sa)) for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW), (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)): fd = self.cpu.fielddescrof(S, 'x') @@ -1240,7 +1231,9 @@ def test_new_with_vtable(self): cpu = self.cpu t_box, T_box = self.alloc_instance(self.T) - cpu.set_class_sizes({T_box.value: cpu.sizeof(self.T)}) + vtable = llmemory.cast_adr_to_ptr( + llmemory.cast_int_to_adr(T_box.value), heaptracker.VTABLETYPE) + heaptracker.register_known_gctype(cpu, vtable, self.T) r1 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') r2 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') assert r1.value != r2.value @@ -1256,11 +1249,11 @@ s = lltype.cast_opaque_ptr(lltype.Ptr(self.T), r1.value) assert s.parent.chr1 == chr(190) assert s.parent.chr2 == chr(150) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1313 - self.cpu.do_setfield_gc(r1, BoxInt(1333), descrshort) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1333 + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1313 + self.cpu.bh_setfield_gc_i(r1.value, descrshort, 1333) + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1333 r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int', descr=descrshort) assert r.value == 1333 @@ -1327,11 +1320,13 @@ self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 assert self.cpu.get_latest_value_ref(1) == xptr - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) ytp.subclassrange_min = 2 @@ -1349,7 +1344,9 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == yptr + assert not self.cpu.grab_exc_value() # cleared exc_tp = xtp exc_ptr = xptr @@ -1365,11 +1362,13 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == xptr self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_cond_call_gc_wb(self): def func_void(a, b): @@ -1546,108 +1545,92 @@ A = lltype.GcArray(lltype.Char) descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) - x = cpu.do_arraylen_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), - descr_A) - assert x.value == 5 + x = cpu.bh_arraylen_gc(descr_A, + lltype.cast_opaque_ptr(llmemory.GCREF, a)) + assert x == 5 # a[2] = 'Y' - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2), - descr_A) - assert x.value == ord('Y') + x = cpu.bh_getarrayitem_gc_i( + descr_A, lltype.cast_opaque_ptr(llmemory.GCREF, a), 2) + assert x == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3), - descr_B) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 3) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a if self.cpu.supports_floats: C = lltype.GcArray(lltype.Float) c = lltype.malloc(C, 6) c[3] = 3.5 descr_C = cpu.arraydescrof(C) - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(3), - descr_C) - assert isinstance(x, BoxFloat) - assert x.getfloat() == 3.5 - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(4), - BoxFloat(4.5), descr_C) + x = cpu.bh_getarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 3) + assert x == 3.5 + cpu.bh_setarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 4, 4.5) assert c[4] == 4.5 s = rstr.mallocstr(6) - x = cpu.do_strlen( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))) - assert x.value == 6 + x = cpu.bh_strlen(lltype.cast_opaque_ptr(llmemory.GCREF, s)) + assert x == 6 # s.chars[3] = 'X' - x = cpu.do_strgetitem( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)) - assert x.value == ord('X') + x = cpu.bh_strgetitem(lltype.cast_opaque_ptr(llmemory.GCREF, s), 3) + assert x == ord('X') # S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A)), ('z', lltype.Float)) descrfld_x = cpu.fielddescrof(S, 'x') s = lltype.malloc(S) s.x = 'Z' - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_x) - assert x.value == ord('Z') - # - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(ord('4')), - descrfld_x) + x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x) + assert x == ord('Z') + # + cpu.bh_setfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x, + ord('4')) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_y) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a # s.y = lltype.nullptr(A) - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x, - descrfld_y) + cpu.bh_setfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y, x) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char)) #, ('y', lltype.Ptr(A))) descrfld_rx = cpu.fielddescrof(RS, 'x') rs = lltype.malloc(RS, immortal=True) rs.x = '?' - x = cpu.do_getfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + x = cpu.bh_getfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx) - assert x.value == ord('?') + assert x == ord('?') # - cpu.do_setfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(ord('!')), - descrfld_rx) + cpu.bh_setfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), + descrfld_rx, ord('!')) assert rs.x == '!' # if self.cpu.supports_floats: descrfld_z = cpu.fielddescrof(S, 'z') - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxFloat(3.5), - descrfld_z) + cpu.bh_setfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_z, 3.5) assert s.z == 3.5 s.z = 3.2 - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + x = cpu.bh_getfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), descrfld_z) - assert x.getfloat() == 3.2 + assert x == 3.2 ### we don't support in the JIT for now GC pointers ### stored inside non-GC structs. #descrfld_ry = cpu.fielddescrof(RS, 'y') @@ -1665,45 +1648,43 @@ #assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new(descrsize) - assert isinstance(x, BoxPtr) - x.getref(lltype.Ptr(S)) + x = cpu.bh_new(descrsize) + lltype.cast_opaque_ptr(lltype.Ptr(S), x) # type check # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - vtable2_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)) - cpu.set_class_sizes({vtable2_int: descrsize2}) - x = cpu.do_new_with_vtable(ConstInt(vtable2_int)) - assert isinstance(x, BoxPtr) + vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2)) + heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT) + x = cpu.bh_new_with_vtable(descrsize2, vtable2_int) + lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check # well... #assert x.getref(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array(BoxInt(7), arraydescr) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(A))) == 7 - # - cpu.do_setarrayitem_gc( - x, BoxInt(5), BoxInt(ord('*')), descr_A) - assert x.getref(lltype.Ptr(A))[5] == '*' - # - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), - BoxInt(1), x, - descr_B) - assert b[1] == x.getref(lltype.Ptr(A)) - # - x = cpu.do_newstr(BoxInt(5)) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(rstr.STR)).chars) == 5 - # - cpu.do_strsetitem(x, BoxInt(4), BoxInt(ord('/'))) - assert x.getref(lltype.Ptr(rstr.STR)).chars[4] == '/' - # - x = cpu.do_newstr(BoxInt(5)) - y = cpu.do_cast_ptr_to_int(x) - assert isinstance(y, BoxInt) - assert y.value == cpu.cast_gcref_to_int(x.value) + x = cpu.bh_new_array(arraydescr, 7) + array = lltype.cast_opaque_ptr(lltype.Ptr(A), x) + assert len(array) == 7 + # + cpu.bh_setarrayitem_gc_i(descr_A, x, 5, ord('*')) + assert array[5] == '*' + # + cpu.bh_setarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 1, x) + assert b[1] == array + # + x = cpu.bh_newstr(5) + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), x) + assert len(str.chars) == 5 + # + cpu.bh_strsetitem(x, 4, ord('/')) + assert str.chars[4] == '/' + # +## x = cpu.bh_newstr(5) +## y = cpu.bh_cast_ptr_to_int(x) +## z = cpu.bh_cast_ptr_to_int(x) +## y = rffi.get_real_int(y) +## z = rffi.get_real_int(z) +## assert type(y) == type(z) == int and y == z def test_sorting_of_fields(self): S = self.S @@ -1716,7 +1697,7 @@ def test_guards_nongc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) vbox = BoxInt(v) ops = [ (rop.GUARD_NONNULL, vbox, False), @@ -1819,6 +1800,9 @@ malloc = staticmethod(ootype.new) nullptr = staticmethod(ootype.null) + def setup_class(cls): + py.test.skip("ootype tests skipped") + @classmethod def get_funcbox(cls, cpu, func_ptr): return BoxObj(ootype.cast_to_object(func_ptr)) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_ll_random.py Fri Jun 18 20:55:39 2010 @@ -3,8 +3,9 @@ from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr -from pypy.jit.metainterp.history import ConstAddr, BoxPtr, BoxInt +from pypy.jit.metainterp.history import BoxPtr, BoxInt from pypy.jit.metainterp.history import BasicFailDescr +from pypy.jit.codewriter import heaptracker from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask from pypy.rpython.llinterp import LLException @@ -19,13 +20,11 @@ self.runicodes = [] self.structure_types = [] self.structure_types_and_vtables = [] - self.class_sizes_cache = [] def fork(self, cpu, loop, vars): fork = test_random.OperationBuilder.fork(self, cpu, loop, vars) fork.structure_types = self.structure_types fork.structure_types_and_vtables = self.structure_types_and_vtables - fork.class_sizes_cache = self.class_sizes_cache return fork def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): @@ -107,11 +106,7 @@ vtable.name[len(name)] = '\x00' self.structure_types_and_vtables.append((S, vtable)) # - vtable_adr = llmemory.cast_ptr_to_adr(vtable) - vtable_int = self.cpu.cast_adr_to_int(vtable_adr) - descr = self.cpu.sizeof(S) - self.class_sizes_cache.append((vtable_int, descr)) - self.cpu.set_class_sizes(dict(self.class_sizes_cache)) + heaptracker.register_known_gctype(self.cpu, vtable, S) # return S, vtable @@ -186,6 +181,9 @@ # ____________________________________________________________ +def ConstAddr(addr, cpu): + return ConstInt(heaptracker.adr2int(addr)) + class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): ptrvars = [(v, S) for (v, S) in builder.ptrvars @@ -507,8 +505,6 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(), descr=BasicFailDescr()) op.fail_args = fail_subset @@ -525,8 +521,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(), descr=BasicFailDescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) @@ -546,8 +540,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/test/test_random.py Fri Jun 18 20:55:39 2010 @@ -4,7 +4,7 @@ from pypy.jit.backend.test import conftest as demo_conftest from pypy.jit.metainterp.history import BasicFailDescr, TreeLoop from pypy.jit.metainterp.history import BoxInt, ConstInt, LoopToken -from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat, Const from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute_nonspec @@ -17,9 +17,14 @@ def __init__(self, subops): self.operations = subops +class FakeMetaInterp(object): + def execute_raised(self, exc, constant=False): + self._got_exc = exc + class OperationBuilder(object): def __init__(self, cpu, loop, vars): self.cpu = cpu + self.fakemetainterp = FakeMetaInterp() self.loop = loop self.intvars = [box for box in vars if isinstance(box, BoxInt)] self.boolvars = [] # subset of self.intvars @@ -40,7 +45,9 @@ return fork def do(self, opnum, argboxes, descr=None): - v_result = execute_nonspec(self.cpu, opnum, argboxes, descr) + self.fakemetainterp._got_exc = None + v_result = execute_nonspec(self.cpu, self.fakemetainterp, + opnum, argboxes, descr) if isinstance(v_result, Const): v_result = v_result.clonebox() self.loop.operations.append(ResOperation(opnum, argboxes, v_result, @@ -56,11 +63,14 @@ if S == S2 and not (isinstance(v, ConstPtr) and isinstance(v2, ConstPtr)): if r.random() < 0.5: - return self.do(rop.OOIS, [v, v2]) + return self.do(rop.PTR_EQ, [v, v2]) else: - return self.do(rop.OOISNOT, [v, v2]) + return self.do(rop.PTR_NE, [v, v2]) v = r.choice(self.intvars) - return self.do(rop.INT_IS_TRUE, [v]) + if r.random() < 0.7: + return self.do(rop.INT_IS_TRUE, [v]) + else: + return self.do(rop.INT_IS_ZERO, [v]) def subset_of_intvars(self, r): subset = [] @@ -79,16 +89,16 @@ for v in op.args: if v in names: args.append(names[v]) - elif isinstance(v, ConstAddr): - try: - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - except AttributeError: - args.append('ConstAddr(...)') - else: - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) +## elif isinstance(v, ConstAddr): +## try: +## name = ''.join([v.value.ptr.name[i] +## for i in range(len(v.value.ptr.name)-1)]) +## except AttributeError: +## args.append('ConstAddr(...)') +## else: +## args.append( +## 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' +## % name) elif isinstance(v, ConstFloat): args.append('ConstFloat(%r)' % v.value) elif isinstance(v, ConstInt): @@ -264,8 +274,8 @@ fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) - if builder.cpu._overflow_flag: # overflow detected - del builder.cpu._overflow_flag + if builder.fakemetainterp._got_exc: # overflow detected + assert isinstance(builder.fakemetainterp._got_exc, OverflowError) op = ResOperation(rop.GUARD_OVERFLOW, [], None) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including @@ -413,7 +423,7 @@ OPERATIONS.append(UnaryOperation(_op)) OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) -OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True)) +OPERATIONS.append(UnaryOperation(rop.INT_IS_ZERO, boolres=True)) OPERATIONS.append(ConstUnaryOperation(rop.SAME_AS, boolres='sometimes')) for _op in [rop.INT_ADD_OVF, @@ -434,8 +444,6 @@ ]: OPERATIONS.append(UnaryFloatOperation(_op)) -OPERATIONS.append(UnaryFloatOperation(rop.FLOAT_IS_TRUE, boolres=True)) - OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT)) OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT)) @@ -587,8 +595,8 @@ def run_loop(self): cpu = self.builder.cpu self.clear_state() - assert not cpu.get_exception() - assert not cpu.get_exc_value() + exc = cpu.grab_exc_value() + assert not exc for i, box in enumerate(self.startvars): if isinstance(box, BoxInt): @@ -609,15 +617,13 @@ self.expected[v], i) ) + exc = cpu.grab_exc_value() if (self.guard_op is not None and self.guard_op.is_guard_exception()): if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: - assert cpu.get_exception() - assert cpu.get_exc_value() - cpu.clear_exception() + assert exc else: - assert not cpu.get_exception() - assert not cpu.get_exc_value() + assert not exc def build_bridge(self): def exc_handling(guard_op): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Fri Jun 18 20:55:39 2010 @@ -796,8 +796,8 @@ genop_int_ne = _cmpop("NE", "NE") genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") - genop_oois = genop_int_eq - genop_ooisnot = genop_int_ne + genop_ptr_eq = genop_int_eq + genop_ptr_ne = genop_int_ne genop_float_lt = _cmpop_float('B') genop_float_le = _cmpop_float('BE') @@ -817,8 +817,8 @@ genop_guard_int_ne = _cmpop_guard("NE", "NE", "E", "E") genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") - genop_guard_oois = genop_guard_int_eq - genop_guard_ooisnot = genop_guard_int_ne + genop_guard_ptr_eq = genop_guard_int_eq + genop_guard_ptr_ne = genop_guard_int_ne genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") @@ -852,25 +852,6 @@ # Following what gcc does: res = x & 0x7FFFFFFFFFFFFFFF self.mc.ANDPD(arglocs[0], heap(self.float_const_abs_addr)) - def genop_guard_float_is_true(self, op, guard_op, addr, arglocs, resloc): - guard_opnum = guard_op.opnum - loc0, loc1 = arglocs - self.mc.XORPD_xx(loc0.value, loc0.value) - self.mc.UCOMISD(loc0, loc1) - mc = self.mc._mc - if guard_opnum == rop.GUARD_TRUE: - mc.J_il8(rx86.Conditions['P'], 6) - mc.J_il(rx86.Conditions['Z'], addr) - return mc.tell() - 4 - else: - mc.J_il8(rx86.Conditions['P'], 2) - mc.J_il8(rx86.Conditions['Z'], 5) - return self.implement_guard(addr) - - def genop_float_is_true(self, op, arglocs, resloc): - self.mc.XORPD_xx(arglocs[0].value, arglocs[0].value) - self.genop_float_ne(op, arglocs, resloc) - def genop_cast_float_to_int(self, op, arglocs, resloc): self.mc.CVTTSD2SI(resloc, arglocs[0]) @@ -891,7 +872,7 @@ self.mc.SET_ir(rx86.Conditions['NE'], rl.value) self.mc.MOVZX8(resloc, rl) - def genop_guard_bool_not(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_zero(self, op, guard_op, addr, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm(0)) if guard_opnum == rop.GUARD_TRUE: @@ -899,13 +880,15 @@ else: return self.implement_guard(addr, 'Z') - def genop_bool_not(self, op, arglocs, resloc): - self.mc.XOR(arglocs[0], imm(1)) + def genop_int_is_zero(self, op, arglocs, resloc): + self.mc.CMP(arglocs[0], imm8(0)) + rl = resloc.lowest8bits() + self.mc.SET_ir(rx86.Conditions['E'], rl.value) + self.mc.MOVZX8(resloc, rl) def genop_same_as(self, op, arglocs, resloc): self.mov(arglocs[0], resloc) - genop_cast_ptr_to_int = genop_same_as - genop_virtual_ref = genop_same_as + #genop_cast_ptr_to_int = genop_same_as def genop_int_mod(self, op, arglocs, resloc): if IS_X86_32: @@ -1263,13 +1246,8 @@ n = self.CODE_HOLE mc.writechr(n) mc.writechr(self.CODE_STOP) - # preallocate the fail_boxes - i = len(failargs) - 1 - if i >= 0: - self.fail_boxes_int.get_addr_for_num(i) - self.fail_boxes_ptr.get_addr_for_num(i) - if self.cpu.supports_floats: - self.fail_boxes_float.get_addr_for_num(i) + # assert that the fail_boxes lists are big enough + assert len(failargs) <= self.fail_boxes_int.SIZE def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager @@ -1314,39 +1292,6 @@ arglocs.append(loc) return arglocs[:] - def make_boxes_from_latest_values(self, bytecode): - bytecode = rffi.cast(rffi.UCHARP, bytecode) - boxes = [] - while 1: - # decode the next instruction from the bytecode - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - kind = code & 3 - while code > 0x7F: - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - index = len(boxes) - if kind == self.DESCR_INT: - box = BoxInt(self.fail_boxes_int.getitem(index)) - elif kind == self.DESCR_REF: - box = BoxPtr(self.fail_boxes_ptr.getitem(index)) - # clear after reading (xxx duplicates - # get_latest_value_ref()) - self.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - elif kind == self.DESCR_FLOAT: - box = BoxFloat(self.fail_boxes_float.getitem(index)) - else: - assert kind == self.DESCR_SPECIAL - if code == self.CODE_STOP: - break - elif code == self.CODE_HOLE: - box = None - else: - assert 0, "bad code" - boxes.append(box) - return boxes - @rgc.no_collect def grab_frame_values(self, bytecode, frame_addr, allregisters): # no malloc allowed here!! @@ -1411,7 +1356,7 @@ # if not we_are_translated(): assert bytecode[4] == 0xCC - # fail_index = rffi.cast(rffi.LONGP, bytecode)[0] + self.fail_boxes_count = num fail_index = rffi.cast(rffi.INTP, bytecode)[0] fail_index = rffi.cast(lltype.Signed, fail_index) return fail_index @@ -1571,8 +1516,6 @@ self.mc.AND(eax, imm(0xff)) elif size == 2: self.mc.AND(eax, imm(0xffff)) - - genop_call_pure = genop_call def genop_guard_call_may_force(self, op, guard_op, addr, arglocs, result_loc): @@ -1591,28 +1534,80 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.J_il8(rx86.Conditions['E'], 0) # patched later + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + # patched later + mc.J_il8(rx86.Conditions['E'], 0) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP_l8(0) # patched later + if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + mc.JMP_l8(0) # jump to done, patched later jmp_location = mc.get_relative_pos() + # + # Path B: fast path. Must load the return value, and reset the token offset = jmp_location - je_location assert 0 < offset <= 127 mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + # + # Reset the vable token --- XXX really too much special logic here:-( + if self.cpu.index_of_virtualizable >= 0: + from pypy.jit.backend.llsupport.descr import BaseFieldDescr + fielddescr = self.cpu.vable_token_descr + assert isinstance(fielddescr, BaseFieldDescr) + ofs = fielddescr.offset + mc.MOV(eax, arglocs[1]) + mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + # in the line above, TOKEN_NONE = 0 + # + if op.result is not None: + # load the return value from fail_boxes_xxx[0] + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location - assert 0 < offset <= 127 + assert 0 <= offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: - self.mc.FSTP_b(result_loc.value) - else: - assert result_loc is eax or result_loc is xmm0 or result_loc is None self.mc.CMP_bi(FORCE_INDEX_OFS, 0) return self.implement_guard(addr, 'L') @@ -1645,7 +1640,7 @@ # misaligned stack in the call, but it's ok because the write barrier # is not going to call anything more. Also, this assumes that the # write barrier does not touch the xmm registers. - mc.CALL_l(descr.get_write_barrier_fn(self.cpu)) + mc.CALL(heap(descr.get_write_barrier_fn(self.cpu))) for i in range(len(arglocs)): loc = arglocs[i] assert isinstance(loc, RegLoc) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regalloc.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,7 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, ConstAddr, BoxPtr, + ResOperation, BoxPtr, LoopToken, INT, REF, FLOAT) from pypy.jit.backend.x86.regloc import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr @@ -11,6 +11,7 @@ from pypy.rlib import rgc from pypy.jit.backend.llsupport import symbolic from pypy.jit.backend.x86.jump import remap_frame_layout +from pypy.jit.codewriter import heaptracker from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr @@ -36,8 +37,6 @@ print "convert_to_imm: ConstPtr needs special care" raise AssertionError return imm(rffi.cast(lltype.Signed, c.value)) - elif isinstance(c, ConstAddr): - return imm(ll2ctypes.cast_adr_to_int(c.value)) else: print "convert_to_imm: got a %s" % c raise AssertionError @@ -564,8 +563,8 @@ consider_uint_lt = _consider_compop consider_uint_le = _consider_compop consider_uint_ge = _consider_compop - consider_oois = _consider_compop - consider_ooisnot = _consider_compop + consider_ptr_eq = _consider_compop + consider_ptr_ne = _consider_compop def _consider_float_op(self, op): loc1 = self.xrm.loc(op.args[1]) @@ -607,20 +606,6 @@ self.Perform(op, [loc0], loc0) self.xrm.possibly_free_var(op.args[0]) - def consider_float_is_true(self, op, guard_op): - # doesn't need arg to be in a register - tmpbox0 = TempBox() - loc0 = self.xrm.force_allocate_reg(tmpbox0) - loc1 = self.xrm.loc(op.args[0]) - arglocs = [loc0, loc1] - self.xrm.possibly_free_var(op.args[0]) - self.xrm.possibly_free_var(tmpbox0) - if guard_op is not None: - self.perform_with_guard(op, guard_op, arglocs, None) - else: - loc2 = self.rm.force_allocate_reg(op.result, need_lower_byte=True) - self.Perform(op, arglocs, loc2) - def consider_cast_float_to_int(self, op): loc0 = self.xrm.make_sure_var_in_reg(op.args[0], imm_fine=False) loc1 = self.rm.force_allocate_reg(op.result) @@ -659,7 +644,6 @@ def consider_call(self, op): self._consider_call(op) - consider_call_pure = consider_call def consider_call_may_force(self, op, guard_op): assert guard_op is not None @@ -670,7 +654,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index]) else: @@ -739,7 +723,7 @@ def consider_new_with_vtable(self, op): classint = op.args[0].getint() - descrsize = self.assembler.cpu.class_sizes[classint] + descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint) if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize): self._fastpath_malloc(op, descrsize) self.assembler.set_vtable(eax, imm(classint)) @@ -903,22 +887,14 @@ resloc = self.rm.force_allocate_reg(op.result, need_lower_byte=True) self.Perform(op, [argloc], resloc) - def consider_bool_not(self, op, guard_op): - if guard_op is not None: - # doesn't need arg to be in a register - argloc = self.loc(op.args[0]) - self.rm.possibly_free_var(op.args[0]) - self.perform_with_guard(op, guard_op, [argloc], None) - else: - self.consider_int_neg(op) + consider_int_is_zero = consider_int_is_true def consider_same_as(self, op): argloc = self.loc(op.args[0]) self.possibly_free_var(op.args[0]) resloc = self.force_allocate_reg(op.result) self.Perform(op, [argloc], resloc) - consider_cast_ptr_to_int = consider_same_as - consider_virtual_ref = consider_same_as + #consider_cast_ptr_to_int = consider_same_as def consider_strlen(self, op): base_loc = self.rm.make_sure_var_in_reg(op.args[0], op.args) @@ -977,9 +953,6 @@ def consider_debug_merge_point(self, op): pass - def consider_virtual_ref_finish(self, op): - self.possibly_free_vars(op.args) - def get_mark_gc_roots(self, gcrootmap): shape = gcrootmap.get_basic_shape() for v, val in self.fm.frame_bindings.items(): @@ -987,6 +960,8 @@ assert isinstance(val, StackLoc) gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position)) for v, reg in self.rm.reg_bindings.items(): + if reg is eax: + continue # ok to ignore this one if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)): if reg is ebx: gcrootmap.add_ebx(shape) @@ -995,7 +970,8 @@ elif reg is edi: gcrootmap.add_edi(shape) else: - assert reg is eax # ok to ignore this one + print "[get_mark_gc_roots] bogus register", reg + assert False return gcrootmap.compress_callshape(shape) def consider_force_token(self, op): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Fri Jun 18 20:55:39 2010 @@ -89,7 +89,9 @@ # XXX: Does this even make sense for an immediate? width = WORD def __init__(self, value): - self.value = value + from pypy.rpython.lltypesystem import rffi, lltype + # force as a real int + self.value = rffi.cast(lltype.Signed, value) def location_code(self): return 'i' Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Fri Jun 18 20:55:39 2010 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp import history, compile @@ -69,19 +70,20 @@ return self.assembler.fail_boxes_float.getitem(index) def get_latest_value_ref(self, index): - ptrvalue = self.assembler.fail_boxes_ptr.getitem(index) - # clear after reading - self.assembler.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - return ptrvalue + return self.assembler.fail_boxes_ptr.getitem(index) + + def get_latest_value_count(self): + return self.assembler.fail_boxes_count + + def clear_latest_values(self, count): + setitem = self.assembler.fail_boxes_ptr.setitem + null = lltype.nullptr(llmemory.GCREF.TO) + for index in range(count): + setitem(index, null) def get_latest_force_token(self): return self.assembler.fail_ebp + FORCE_INDEX_OFS - def make_boxes_from_latest_values(self, faildescr): - return self.assembler.make_boxes_from_latest_values( - faildescr._x86_failure_recovery_bytecode) - def execute_token(self, executable_token): addr = executable_token._x86_bootstrap_code func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr) @@ -156,9 +158,6 @@ CPU = CPU386 -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(CPU) - # silence warnings history.LoopToken._x86_param_depth = 0 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/support.py Fri Jun 18 20:55:39 2010 @@ -4,6 +4,8 @@ ATP = lltype.GcArray(TP) class ValuesArray(object): + SIZE = size + def __init__(self): self.ar = lltype.malloc(ATP, size, zero=True, immortal=True) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Fri Jun 18 20:55:39 2010 @@ -80,35 +80,6 @@ assert ([loc.assembler() for loc in newlocs] == [loc.assembler() for loc in locs if loc is not None]) - # finally, test make_boxes_from_latest_values(), which should - # reproduce the holes - expected_classes = [BoxInt, BoxPtr, BoxFloat, - BoxInt, BoxPtr, BoxFloat, - type(None), type(None), - BoxInt, BoxPtr, BoxFloat] - ptrvalues = {} - S = lltype.GcStruct('S') - for i, cls in enumerate(expected_classes): - if cls == BoxInt: - assembler.fail_boxes_int.setitem(i, 1000 + i) - elif cls == BoxPtr: - s = lltype.malloc(S) - s_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s) - ptrvalues[i] = s_ref - assembler.fail_boxes_ptr.setitem(i, s_ref) - elif cls == BoxFloat: - assembler.fail_boxes_float.setitem(i, 42.5 + i) - boxes = assembler.make_boxes_from_latest_values(bytecode_addr) - assert len(boxes) == len(locs) == len(expected_classes) - for i, (box, expected_class) in enumerate(zip(boxes, expected_classes)): - assert type(box) is expected_class - if expected_class == BoxInt: - assert box.value == 1000 + i - elif expected_class == BoxPtr: - assert box.value == ptrvalues[i] - elif expected_class == BoxFloat: - assert box.value == 42.5 + i - # ____________________________________________________________ def test_failure_recovery_func_no_floats(): @@ -264,6 +235,13 @@ # bits of the float were correctly saved and restored. assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + # verify that until clear_latest_values() is called, reading the + # same values multiple times work + for i in range(len(content)): + assert assembler.fail_boxes_int.getitem(i) == expected_ints[i] + assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i] + assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + class FakeProfileAgent(object): def __init__(self): self.functions = [] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_basic.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,7 @@ from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.test import test_basic -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE class Jit386Mixin(test_basic.LLJitMixin): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_gc_integration.py Fri Jun 18 20:55:39 2010 @@ -3,9 +3,10 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription from pypy.jit.backend.detect_cpu import getcpuclass @@ -21,7 +22,6 @@ from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc from pypy.jit.backend.x86.regalloc import X86RegisterManager, X86FrameManager,\ X86XMMRegisterManager -from pypy.rpython.annlowlevel import llhelper CPU = getcpuclass() @@ -227,10 +227,12 @@ self.nodedescr = nodedescr vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) vtable_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable)) - NODE2 = lltype.Struct('node2', ('tid', lltype.Signed), + NODE2 = lltype.GcStruct('node2', + ('parent', rclass.OBJECT), + ('tid', lltype.Signed), ('vtable', lltype.Ptr(rclass.OBJECT_VTABLE))) descrsize = cpu.sizeof(NODE2) - cpu.set_class_sizes({vtable_int: descrsize}) + heaptracker.register_known_gctype(cpu, vtable, NODE2) self.descrsize = descrsize self.vtable_int = vtable_int @@ -284,4 +286,4 @@ assert gc_ll_descr.nursery[0] == self.descrsize.tid assert gc_ll_descr.nursery[1] == self.vtable_int nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2) + assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*3) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, LoopToken, BasicFailDescr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache @@ -220,10 +220,9 @@ ''' S = lltype.GcStruct('S') ptr = lltype.malloc(S) + self.cpu.clear_latest_values(2) self.interpret(ops, [0, ptr]) assert self.getptr(0, lltype.Ptr(S)) == ptr - assert not self.cpu.assembler.fail_boxes_ptr.getitem(0) - assert not self.cpu.assembler.fail_boxes_ptr.getitem(1) def test_exception_bridge_no_exception(self): ops = ''' @@ -531,18 +530,20 @@ assert self.getint(0) == 0 def test_bug_float_is_true_stack(self): + # NB. float_is_true no longer exists. Unsure if keeping this test + # makes sense any more. ops = ''' [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9] - i0 = float_is_true(f0) - i1 = float_is_true(f1) - i2 = float_is_true(f2) - i3 = float_is_true(f3) - i4 = float_is_true(f4) - i5 = float_is_true(f5) - i6 = float_is_true(f6) - i7 = float_is_true(f7) - i8 = float_is_true(f8) - i9 = float_is_true(f9) + i0 = float_ne(f0, 0.0) + i1 = float_ne(f1, 0.0) + i2 = float_ne(f2, 0.0) + i3 = float_ne(f3, 0.0) + i4 = float_ne(f4, 0.0) + i5 = float_ne(f5, 0.0) + i6 = float_ne(f6, 0.0) + i7 = float_ne(f7, 0.0) + i8 = float_ne(f8, 0.0) + i9 = float_ne(f9, 0.0) finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) ''' loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9]) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc2.py Fri Jun 18 20:55:39 2010 @@ -37,7 +37,7 @@ ResOperation(rop.INT_MUL, [v1, v1], v2), ResOperation(rop.INT_MUL, [v2, v1], v3), ResOperation(rop.INT_IS_TRUE, [v2], tmp5), - ResOperation(rop.BOOL_NOT, [tmp5], v4), + ResOperation(rop.INT_IS_ZERO, [tmp5], v4), ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()), ] cpu = CPU(None, None) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Fri Jun 18 20:55:39 2010 @@ -264,9 +264,11 @@ self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) if guard == rop.GUARD_FALSE: - assert result == execute(self.cpu, op, None, b).value + assert result == execute(self.cpu, None, + op, None, b).value else: - assert result != execute(self.cpu, op, None, b).value + assert result != execute(self.cpu, None, + op, None, b).value def test_stuff_followed_by_guard(self): @@ -309,7 +311,7 @@ self.cpu.set_future_value_int(i, box.value) self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) - expected = execute(self.cpu, op, None, a, b).value + expected = execute(self.cpu, None, op, None, a, b).value if guard == rop.GUARD_FALSE: assert result == expected else: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_send.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_send.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_send.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,6 @@ import py from pypy.jit.metainterp.test.test_send import SendTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rlib import jit class TestSend(Jit386Mixin, SendTests): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_zrpy_gc.py Fri Jun 18 20:55:39 2010 @@ -94,7 +94,7 @@ def run(cbuilder, args=''): # pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': str(pypylog)}) + data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) return data.strip() def compile_and_run(f, gc, **kwds): @@ -174,7 +174,7 @@ def run(self, name, n=2000): pypylog = udir.join('TestCompileHybrid.log') res = self.cbuilder.cmdexec("%s %d" %(name, n), - env={'PYPYLOG': str(pypylog)}) + env={'PYPYLOG': ':%s' % pypylog}) assert int(res) == 20 def run_orig(self, name, n, x): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_ztranslation.py Fri Jun 18 20:55:39 2010 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.jitprof import Profiler from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.test.support import CCompiledMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.translator.translator import TranslationContext from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 @@ -39,7 +39,7 @@ return abs(x) jitdriver = JitDriver(greens = [], - reds = ['frame', 'total', 'j'], + reds = ['total', 'frame', 'j'], virtualizables = ['frame']) def f(i, j): for param in unroll_parameters: @@ -73,7 +73,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -132,8 +132,14 @@ jitdriver = JitDriver(greens = [], reds = ['n', 'total']) + class ImDone(Exception): + def __init__(self, resvalue): + self.resvalue = resvalue + @dont_look_inside - def f(x): + def f(x, total): + if x <= 3: + raise ImDone(total * 10) if x > 20: return 2 raise ValueError @@ -154,16 +160,16 @@ return Sub() else: return Base() - def main(i): + def myportal(i): jitdriver.set_param("threshold", 3) jitdriver.set_param("trace_eagerness", 2) total = 0 n = i - while n > 3: + while True: jitdriver.can_enter_jit(n=n, total=total) jitdriver.jit_merge_point(n=n, total=total) try: - total += f(n) + total += f(n, total) except ValueError: total += 1 try: @@ -171,7 +177,11 @@ except ValueError: total -= 1 n -= h(n).meth() # this is to force a GUARD_CLASS - return total * 10 + def main(i): + try: + myportal(i) + except ImDone, e: + return e.resvalue # XXX custom fishing, depends on the exact env var and format logfile = udir.join('test_ztranslation.log') Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/compile.py Fri Jun 18 20:55:39 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import debug_start, debug_stop from pypy.conftest import option +from pypy.tool.sourcetools import func_with_new_name from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import TreeLoop, Box, History, LoopToken @@ -14,8 +15,10 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.jit.metainterp.optimizeutil import InvalidLoop -class GiveUp(Exception): - pass +def giveup(): + from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole + from pypy.jit.metainterp.jitprof import ABORT_BRIDGE + raise SwitchToBlackhole(ABORT_BRIDGE) def show_loop(metainterp_sd, loop=None, error=None): # debugging @@ -153,6 +156,7 @@ assert metainterp_sd.result_type == 'ref' cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): @@ -165,6 +169,7 @@ def handle_fail(self, metainterp_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value) @@ -220,6 +225,11 @@ rd_virtuals = None rd_pendingfields = None + CNT_INT = -0x20000000 + CNT_REF = -0x40000000 + CNT_FLOAT = -0x60000000 + CNT_MASK = 0x1FFFFFFF + def __init__(self, metainterp_sd, original_greenkey): ResumeDescr.__init__(self, original_greenkey) self.metainterp_sd = metainterp_sd @@ -236,23 +246,64 @@ except ValueError: return # xxx probably very rare else: - self._counter = ~i # use ~(index_of_guarded_box_in_fail_args) + if box.type == history.INT: + cnt = self.CNT_INT + elif box.type == history.REF: + cnt = self.CNT_REF + elif box.type == history.FLOAT: + cnt = self.CNT_FLOAT + else: + assert 0, box.type + # we build the following value for _counter, which is always + # a negative value + self._counter = cnt | i def handle_fail(self, metainterp_sd): + if self.must_compile(metainterp_sd): + return self._trace_and_compile_from_bridge(metainterp_sd) + else: + from pypy.jit.metainterp.blackhole import resume_in_blackhole + resume_in_blackhole(metainterp_sd, self) + assert 0, "unreachable" + + def _trace_and_compile_from_bridge(self, metainterp_sd): from pypy.jit.metainterp.pyjitpl import MetaInterp metainterp = MetaInterp(metainterp_sd) return metainterp.handle_guard_failure(self) + _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd, inputargs_and_holes): + def must_compile(self, metainterp_sd): trace_eagerness = metainterp_sd.state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness else: - box = inputargs_and_holes[~self._counter] - if self._counters is None: - self._counters = ResumeGuardCounters() - counter = self._counters.see(box) + index = self._counter & self.CNT_MASK + typetag = self._counter & ~ self.CNT_MASK + counters = self._counters + if typetag == self.CNT_INT: + intvalue = metainterp_sd.cpu.get_latest_value_int(index) + if counters is None: + self._counters = counters = ResumeGuardCountersInt() + else: + assert isinstance(counters, ResumeGuardCountersInt) + counter = counters.see_int(intvalue) + elif typetag == self.CNT_REF: + refvalue = metainterp_sd.cpu.get_latest_value_ref(index) + if counters is None: + self._counters = counters = ResumeGuardCountersRef() + else: + assert isinstance(counters, ResumeGuardCountersRef) + counter = counters.see_ref(refvalue) + elif typetag == self.CNT_FLOAT: + floatvalue = metainterp_sd.cpu.get_latest_value_float(index) + if counters is None: + self._counters = counters = ResumeGuardCountersFloat() + else: + assert isinstance(counters, ResumeGuardCountersFloat) + counter = counters.see_float(floatvalue) + else: + assert 0, typetag return counter >= trace_eagerness def reset_counter_from_failure(self): @@ -283,17 +334,17 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): def handle_fail(self, metainterp_sd): - from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + # Failures of a GUARD_NOT_FORCED are never compiled, but + # always just blackholed. First fish for the data saved when + # the virtualrefs and virtualizable have been forced by + # handle_async_forcing() just a moment ago. + from pypy.jit.metainterp.blackhole import resume_in_blackhole token = metainterp_sd.cpu.get_latest_force_token() all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - metainterp._already_allocated_resume_virtuals = all_virtuals - return metainterp.handle_guard_failure(self) - - def must_compile(self, metainterp_sd, inputargs_and_holes): - return False # never compile GUARD_NOT_FORCED failures + resume_in_blackhole(metainterp_sd, self, all_virtuals) + assert 0, "unreachable" @staticmethod def force_now(cpu, token): @@ -305,91 +356,101 @@ faildescr.handle_async_forcing(token) def handle_async_forcing(self, force_token): - from pypy.jit.metainterp.pyjitpl import MetaInterp from pypy.jit.metainterp.resume import force_from_resumedata - # To handle the forcing itself, we create a temporary MetaInterp - # as a convenience to move the various data to its proper place. metainterp_sd = self.metainterp_sd - metainterp = MetaInterp(metainterp_sd) - metainterp.history = None # blackholing - liveboxes = metainterp_sd.cpu.make_boxes_from_latest_values(self) - # - expect_virtualizable = metainterp_sd.virtualizable_info is not None - forced_data = force_from_resumedata(metainterp, liveboxes, self, - expect_virtualizable) - virtualizable_boxes, virtualref_boxes, all_virtuals = forced_data - # - # Handle virtualref_boxes: mark each JIT_VIRTUAL_REF as forced - vrefinfo = metainterp_sd.virtualref_info - for i in range(0, len(virtualref_boxes), 2): - virtualbox = virtualref_boxes[i] - vrefbox = virtualref_boxes[i+1] - vrefinfo.forced_single_vref(vrefbox.getref_base(), - virtualbox.getref_base()) - # Handle virtualizable_boxes: store them on the real virtualizable now - if expect_virtualizable: - metainterp_sd.virtualizable_info.forced_vable(virtualizable_boxes) + all_virtuals = force_from_resumedata(metainterp_sd, self) + # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED self.save_data(force_token, all_virtuals) def save_data(self, key, value): globaldata = self.metainterp_sd.globaldata - assert key not in globaldata.resume_virtuals - globaldata.resume_virtuals[key] = value + if we_are_translated(): + assert key not in globaldata.resume_virtuals + globaldata.resume_virtuals[key] = value + else: + rv = globaldata.resume_virtuals_not_translated + for key1, value1 in rv: + assert key1 != key + rv.append((key, value)) def fetch_data(self, key): globaldata = self.metainterp_sd.globaldata - assert key in globaldata.resume_virtuals - data = globaldata.resume_virtuals[key] - del globaldata.resume_virtuals[key] + if we_are_translated(): + assert key in globaldata.resume_virtuals + data = globaldata.resume_virtuals[key] + del globaldata.resume_virtuals[key] + else: + rv = globaldata.resume_virtuals_not_translated + for i in range(len(rv)): + if rv[i][0] == key: + data = rv[i][1] + del rv[i] + break + else: + assert 0, "not found: %r" % (key,) return data -class ResumeGuardCounters(object): - # Completely custom algorithm for now: keep 5 pairs (box, counter), +class AbstractResumeGuardCounters(object): + # Completely custom algorithm for now: keep 5 pairs (value, counter), # and when we need more, we discard the middle pair (middle in the # current value of the counter). That way, we tend to keep the - # boxes with a high counter, but also we avoid always throwing away - # the most recently added box. **THIS ALGO MUST GO AWAY AT SOME POINT** + # values with a high counter, but also we avoid always throwing away + # the most recently added value. **THIS ALGO MUST GO AWAY AT SOME POINT** + pass +def _see(self, newvalue): + # find and update an existing counter + unused = -1 + for i in range(5): + cnt = self.counters[i] + if cnt: + if self.values[i] == newvalue: + cnt += 1 + self.counters[i] = cnt + return cnt + else: + unused = i + # not found. Use a previously unused entry, if there is one + if unused >= 0: + self.counters[unused] = 1 + self.values[unused] = newvalue + return 1 + # no unused entry. Overwrite the middle one. Computed with indices + # a, b, c meaning the highest, second highest, and third highest + # entries. + a = 0 + b = c = -1 + for i in range(1, 5): + if self.counters[i] > self.counters[a]: + c = b; b = a; a = i + elif b < 0 or self.counters[i] > self.counters[b]: + c = b; b = i + elif c < 0 or self.counters[i] > self.counters[c]: + c = i + self.counters[c] = 1 + self.values[c] = newvalue + return 1 + +class ResumeGuardCountersInt(AbstractResumeGuardCounters): def __init__(self): self.counters = [0] * 5 - self.boxes = [None] * 5 + self.values = [0] * 5 + see_int = func_with_new_name(_see, 'see_int') - def see(self, newbox): - newbox = newbox.constbox() - # find and update an existing counter - unused = -1 - for i in range(5): - cnt = self.counters[i] - if cnt: - if newbox.same_constant(self.boxes[i]): - cnt += 1 - self.counters[i] = cnt - return cnt - else: - unused = i - # not found. Use a previously unused entry, if there is one - if unused >= 0: - self.counters[unused] = 1 - self.boxes[unused] = newbox - return 1 - # no unused entry. Overwrite the middle one. Computed with indices - # a, b, c meaning the highest, second highest, and third highest - # entries. - a = 0 - b = c = -1 - for i in range(1, 5): - if self.counters[i] > self.counters[a]: - c = b; b = a; a = i - elif b < 0 or self.counters[i] > self.counters[b]: - c = b; b = i - elif c < 0 or self.counters[i] > self.counters[c]: - c = i - self.counters[c] = 1 - self.boxes[c] = newbox - return 1 +class ResumeGuardCountersRef(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [history.ConstPtr.value] * 5 + see_ref = func_with_new_name(_see, 'see_ref') + +class ResumeGuardCountersFloat(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [0.0] * 5 + see_float = func_with_new_name(_see, 'see_float') class ResumeFromInterpDescr(ResumeDescr): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/executor.py Fri Jun 18 20:55:39 2010 @@ -2,248 +2,213 @@ """ import py -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, check_descr -from pypy.jit.metainterp.history import INT, REF, ConstFloat +from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, check_descr +from pypy.jit.metainterp.history import INT, REF, FLOAT, VOID, AbstractDescr from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop - - -# Operations in the _ALWAYS_PURE part of the table of resoperation.py -# must return a ConstInt or ConstPtr. Other operations must return -# a BoxInt or BoxPtr or None. +from pypy.jit.metainterp.blackhole import BlackholeInterpreter, NULL # ____________________________________________________________ -def do_int_add(cpu, box1, box2): - return ConstInt(intmask(box1.getint() + box2.getint())) - -def do_int_sub(cpu, box1, box2): - return ConstInt(intmask(box1.getint() - box2.getint())) - -def do_int_mul(cpu, box1, box2): - return ConstInt(intmask(box1.getint() * box2.getint())) - -def do_int_floordiv(cpu, box1, box2): - z = llop.int_floordiv(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_uint_floordiv(cpu, box1, box2): - z = llop.uint_floordiv(lltype.Unsigned, r_uint(box1.getint()), - r_uint(box2.getint())) - return ConstInt(intmask(z)) - -def do_int_mod(cpu, box1, box2): - z = llop.int_mod(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_int_and(cpu, box1, box2): - return ConstInt(box1.getint() & box2.getint()) - -def do_int_or(cpu, box1, box2): - return ConstInt(box1.getint() | box2.getint()) - -def do_int_xor(cpu, box1, box2): - return ConstInt(box1.getint() ^ box2.getint()) - -def do_int_rshift(cpu, box1, box2): - return ConstInt(box1.getint() >> box2.getint()) - -def do_int_lshift(cpu, box1, box2): - return ConstInt(intmask(box1.getint() << box2.getint())) - -def do_uint_rshift(cpu, box1, box2): - v = r_uint(box1.getint()) >> r_uint(box2.getint()) - return ConstInt(intmask(v)) - -# ---------- - -def do_int_lt(cpu, box1, box2): - return ConstInt(box1.getint() < box2.getint()) - -def do_int_le(cpu, box1, box2): - return ConstInt(box1.getint() <= box2.getint()) - -def do_int_eq(cpu, box1, box2): - return ConstInt(box1.getint() == box2.getint()) - -def do_int_ne(cpu, box1, box2): - return ConstInt(box1.getint() != box2.getint()) - -def do_int_gt(cpu, box1, box2): - return ConstInt(box1.getint() > box2.getint()) - -def do_int_ge(cpu, box1, box2): - return ConstInt(box1.getint() >= box2.getint()) - -def do_uint_lt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) < r_uint(box2.getint())) - -def do_uint_le(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) <= r_uint(box2.getint())) - -def do_uint_gt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) > r_uint(box2.getint())) - -def do_uint_ge(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) >= r_uint(box2.getint())) - -# ---------- - -def do_int_is_true(cpu, box1): - return ConstInt(bool(box1.getint())) - -def do_int_neg(cpu, box1): - return ConstInt(intmask(-box1.getint())) - -def do_int_invert(cpu, box1): - return ConstInt(~box1.getint()) - -def do_bool_not(cpu, box1): - return ConstInt(not box1.getint()) +def do_call(cpu, metainterp, argboxes, descr): + assert metainterp is not None + # count the number of arguments of the different types + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + type = argboxes[i].type + if type == INT: count_i += 1 + elif type == REF: count_r += 1 + elif type == FLOAT: count_f += 1 + # allocate lists for each type that has at least one argument + if count_i: args_i = [0] * count_i + else: args_i = None + if count_r: args_r = [NULL] * count_r + else: args_r = None + if count_f: args_f = [0.0] * count_f + else: args_f = None + # fill in the lists + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + box = argboxes[i] + if box.type == INT: + args_i[count_i] = box.getint() + count_i += 1 + elif box.type == REF: + args_r[count_r] = box.getref_base() + count_r += 1 + elif box.type == FLOAT: + args_f[count_f] = box.getfloat() + count_f += 1 + # get the function address as an integer + func = argboxes[0].getint() + # do the call using the correct function from the cpu + rettype = descr.get_return_type() + if rettype == INT: + try: + result = cpu.bh_call_i(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0 + return BoxInt(result) + if rettype == REF: + try: + result = cpu.bh_call_r(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = NULL + return BoxPtr(result) + if rettype == FLOAT: + try: + result = cpu.bh_call_f(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0.0 + return BoxFloat(result) + if rettype == VOID: + try: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + return None + raise AssertionError("bad rettype") + +do_call_loopinvariant = do_call +do_call_may_force = do_call + +def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + return BoxPtr(cpu.bh_getarrayitem_gc_r(arraydescr, array, index)) + elif arraydescr.is_array_of_floats(): + return BoxFloat(cpu.bh_getarrayitem_gc_f(arraydescr, array, index)) + else: + return BoxInt(cpu.bh_getarrayitem_gc_i(arraydescr, array, index)) -def do_same_as(cpu, box1): - return box1 +def do_setarrayitem_gc(cpu, _, arraybox, indexbox, itembox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + cpu.bh_setarrayitem_gc_r(arraydescr, array, index, + itembox.getref_base()) + elif arraydescr.is_array_of_floats(): + cpu.bh_setarrayitem_gc_f(arraydescr, array, index, itembox.getfloat()) + else: + cpu.bh_setarrayitem_gc_i(arraydescr, array, index, itembox.getint()) -def do_oois(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() == box2.getint() - elif tp == REF: - x = box1.getref_base() == box2.getref_base() +def do_getfield_gc(cpu, _, structbox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr)) -def do_ooisnot(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() != box2.getint() - elif tp == REF: - x = box1.getref_base() != box2.getref_base() +def do_getfield_raw(cpu, _, structbox, fielddescr): + check_descr(fielddescr) + struct = structbox.getint() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr)) -def do_subclassof(cpu, box1, box2): - return ConstInt(cpu.ts.subclassOf(cpu, box1, box2)) +def do_setfield_gc(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_gc_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_gc_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_gc_i(struct, fielddescr, itembox.getint()) -# ---------- +def do_setfield_raw(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getint() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_raw_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_raw_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_raw_i(struct, fielddescr, itembox.getint()) -def do_int_add_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def exec_new_with_vtable(cpu, clsbox): + from pypy.jit.codewriter import heaptracker + vtable = clsbox.getint() + descr = heaptracker.vtable2descr(cpu, vtable) + return cpu.bh_new_with_vtable(descr, vtable) + +def do_new_with_vtable(cpu, _, clsbox): + return BoxPtr(exec_new_with_vtable(cpu, clsbox)) + +def do_arraycopy(cpu, _, calldescr, funcbox, x1box, x2box, + x3box, x4box, x5box, arraydescr): + cpu.bh_call_v(funcbox.getint(), calldescr, + [x3box.getint(), x4box.getint(), x5box.getint()], + [x1box.getref_base(), x2box.getref_base()], None) + +def do_int_add_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x + y) + z = ovfcheck(a + b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_sub_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_sub_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x - y) + z = ovfcheck(a - b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_mul_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_mul_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x * y) + z = ovfcheck(a * b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -# ---------- - -def do_float_neg(cpu, box1): - return ConstFloat(-box1.getfloat()) - -def do_float_abs(cpu, box1): - return ConstFloat(abs(box1.getfloat())) - -def do_float_is_true(cpu, box1): - return ConstInt(bool(box1.getfloat())) - -def do_float_add(cpu, box1, box2): - return ConstFloat(box1.getfloat() + box2.getfloat()) - -def do_float_sub(cpu, box1, box2): - return ConstFloat(box1.getfloat() - box2.getfloat()) - -def do_float_mul(cpu, box1, box2): - return ConstFloat(box1.getfloat() * box2.getfloat()) - -def do_float_truediv(cpu, box1, box2): - return ConstFloat(box1.getfloat() / box2.getfloat()) - -def do_float_lt(cpu, box1, box2): - return ConstInt(box1.getfloat() < box2.getfloat()) - -def do_float_le(cpu, box1, box2): - return ConstInt(box1.getfloat() <= box2.getfloat()) - -def do_float_eq(cpu, box1, box2): - return ConstInt(box1.getfloat() == box2.getfloat()) - -def do_float_ne(cpu, box1, box2): - return ConstInt(box1.getfloat() != box2.getfloat()) - -def do_float_gt(cpu, box1, box2): - return ConstInt(box1.getfloat() > box2.getfloat()) - -def do_float_ge(cpu, box1, box2): - return ConstInt(box1.getfloat() >= box2.getfloat()) - -def do_cast_float_to_int(cpu, box1): - # note: we need to call int() twice to care for the fact that - # int(-2147483648.0) returns a long :-( - return ConstInt(int(int(box1.getfloat()))) - -def do_cast_int_to_float(cpu, box1): - return ConstFloat(float(box1.getint())) +def do_same_as(cpu, _, box): + return box.clonebox() # ____________________________________________________________ -def do_force_token(cpu): - raise NotImplementedError +##def do_force_token(cpu): +## raise NotImplementedError -def do_virtual_ref(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref(cpu, box1, box2): +## raise NotImplementedError -def do_virtual_ref_finish(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref_finish(cpu, box1, box2): +## raise NotImplementedError -def do_debug_merge_point(cpu, box1): - from pypy.jit.metainterp.warmspot import get_stats - loc = box1._get_str() - get_stats().add_merge_point_location(loc) +##def do_debug_merge_point(cpu, box1): +## from pypy.jit.metainterp.warmspot import get_stats +## loc = box1._get_str() +## get_stats().add_merge_point_location(loc) # ____________________________________________________________ -def make_execute_list(cpuclass): - from pypy.jit.backend.model import AbstractCPU +def _make_execute_list(): if 0: # enable this to trace calls to do_xxx def wrap(fn): def myfn(*args): @@ -266,37 +231,109 @@ # find which list to store the operation in, based on num_args num_args = resoperation.oparity[value] withdescr = resoperation.opwithdescr[value] - if withdescr and num_args >= 0: - num_args += 1 - if num_args not in execute_by_num_args: - execute_by_num_args[num_args] = [None] * (rop._LAST+1) - execute = execute_by_num_args[num_args] + dictkey = num_args, withdescr + if dictkey not in execute_by_num_args: + execute_by_num_args[dictkey] = [None] * (rop._LAST+1) + execute = execute_by_num_args[dictkey] # if execute[value] is not None: - raise Exception("duplicate entry for op number %d" % value) + raise AssertionError("duplicate entry for op number %d"% value) + # + # Fish for a way for the pyjitpl interpreter to delegate + # really running the operation to the blackhole interpreter + # or directly to the cpu. First try the do_xxx() functions + # explicitly encoded above: + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # Maybe the same without the _PURE suffix? if key.endswith('_PURE'): key = key[:-5] - name = 'do_' + key.lower() - if hasattr(cpuclass, name): - execute[value] = wrap(getattr(cpuclass, name)) - elif name in globals(): - execute[value] = wrap(globals()[name]) - else: - assert hasattr(AbstractCPU, name), name - cpuclass._execute_by_num_args = execute_by_num_args + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # If missing, fallback to the bhimpl_xxx() method of the + # blackhole interpreter. This only works if there is a + # method of the exact same name and it accepts simple + # parameters. + name = 'bhimpl_' + key.lower() + if hasattr(BlackholeInterpreter, name): + func = make_execute_function_with_boxes( + key.lower(), + getattr(BlackholeInterpreter, name).im_func) + if func is not None: + execute[value] = func + continue + if value in (rop.FORCE_TOKEN, + rop.CALL_ASSEMBLER, + rop.COND_CALL_GC_WB, + rop.DEBUG_MERGE_POINT, + rop.SETARRAYITEM_RAW, + ): # list of opcodes never executed by pyjitpl + continue + raise AssertionError("missing %r" % (key,)) + return execute_by_num_args +def make_execute_function_with_boxes(name, func): + # Make a wrapper for 'func'. The func is a simple bhimpl_xxx function + # from the BlackholeInterpreter class. The wrapper is a new function + # that receives and returns boxed values. + for argtype in func.argtypes: + if argtype not in ('i', 'r', 'f', 'd', 'cpu'): + return None + if list(func.argtypes).count('d') > 1: + return None + if func.resulttype not in ('i', 'r', 'f', None): + return None + argtypes = unrolling_iterable(func.argtypes) + resulttype = func.resulttype + # + def do(cpu, _, *argboxes): + newargs = () + for argtype in argtypes: + if argtype == 'cpu': + value = cpu + elif argtype == 'd': + value = argboxes[-1] + assert isinstance(value, AbstractDescr) + argboxes = argboxes[:-1] + else: + argbox = argboxes[0] + argboxes = argboxes[1:] + if argtype == 'i': value = argbox.getint() + elif argtype == 'r': value = argbox.getref_base() + elif argtype == 'f': value = argbox.getfloat() + newargs = newargs + (value,) + assert not argboxes + # + result = func(*newargs) + # + if resulttype == 'i': return BoxInt(result) + if resulttype == 'r': return BoxPtr(result) + if resulttype == 'f': return BoxFloat(result) + return None + # + do.func_name = 'do_' + name + return do -def get_execute_funclist(cpu, num_args): +def get_execute_funclist(num_args, withdescr): # workaround, similar to the next one - return cpu._execute_by_num_args[num_args] + return EXECUTE_BY_NUM_ARGS[num_args, withdescr] get_execute_funclist._annspecialcase_ = 'specialize:memo' -def get_execute_function(cpu, opnum, num_args): +def get_execute_function(opnum, num_args, withdescr): # workaround for an annotation limitation: putting this code in # a specialize:memo function makes sure the following line is # constant-folded away. Only works if opnum and num_args are # constants, of course. - return cpu._execute_by_num_args[num_args][opnum] + func = EXECUTE_BY_NUM_ARGS[num_args, withdescr][opnum] + assert func is not None, "EXECUTE_BY_NUM_ARGS[%s, %s][%s]" % ( + num_args, withdescr, resoperation.opname[opnum]) + return func get_execute_function._annspecialcase_ = 'specialize:memo' def has_descr(opnum): @@ -305,56 +342,61 @@ has_descr._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, descr, *argboxes): +def execute(cpu, metainterp, opnum, descr, *argboxes): # only for opnums with a fixed arity - if has_descr(opnum): + num_args = len(argboxes) + withdescr = has_descr(opnum) + if withdescr: check_descr(descr) argboxes = argboxes + (descr,) else: assert descr is None - func = get_execute_function(cpu, opnum, len(argboxes)) - assert func is not None - return func(cpu, *argboxes) -execute._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, num_args, withdescr) + return func(cpu, metainterp, *argboxes) # note that the 'argboxes' tuple + # optionally ends with the descr +execute._annspecialcase_ = 'specialize:arg(2)' -def execute_varargs(cpu, opnum, argboxes, descr): +def execute_varargs(cpu, metainterp, opnum, argboxes, descr): # only for opnums with a variable arity (calls, typically) check_descr(descr) - func = get_execute_function(cpu, opnum, -1) - assert func is not None - return func(cpu, argboxes, descr) -execute_varargs._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, -1, True) + return func(cpu, metainterp, argboxes, descr) +execute_varargs._annspecialcase_ = 'specialize:arg(2)' -def execute_nonspec(cpu, opnum, argboxes, descr=None): +def execute_nonspec(cpu, metainterp, opnum, argboxes, descr=None): arity = resoperation.oparity[opnum] assert arity == -1 or len(argboxes) == arity if resoperation.opwithdescr[opnum]: check_descr(descr) if arity == -1: - func = get_execute_funclist(cpu, -1)[opnum] - return func(cpu, argboxes, descr) + func = get_execute_funclist(-1, True)[opnum] + return func(cpu, metainterp, argboxes, descr) if arity == 0: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, descr) + func = get_execute_funclist(0, True)[opnum] + return func(cpu, metainterp, descr) if arity == 1: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], descr) + func = get_execute_funclist(1, True)[opnum] + return func(cpu, metainterp, argboxes[0], descr) if arity == 2: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], descr) + func = get_execute_funclist(2, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], descr) if arity == 3: - func = get_execute_funclist(cpu, 4)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2], descr) + func = get_execute_funclist(3, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2], + descr) else: assert descr is None if arity == 1: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, argboxes[0]) + func = get_execute_funclist(1, False)[opnum] + return func(cpu, metainterp, argboxes[0]) if arity == 2: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], argboxes[1]) + func = get_execute_funclist(2, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1]) if arity == 3: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2]) + func = get_execute_funclist(3, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2]) raise NotImplementedError + + +EXECUTE_BY_NUM_ARGS = _make_execute_list() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/history.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/history.py Fri Jun 18 20:55:39 2010 @@ -9,6 +9,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -16,6 +17,7 @@ REF = 'r' FLOAT = 'f' HOLE = '_' +VOID = 'v' FAILARGS_LIMIT = 1000 @@ -40,6 +42,7 @@ return "ref" else: raise NotImplementedError("type %s not supported" % TYPE) +getkind._annspecialcase_ = 'specialize:memo' def repr_pointer(box): from pypy.rpython.lltypesystem import rstr @@ -98,7 +101,7 @@ def nonconstbox(self): raise NotImplementedError - def getaddr(self, cpu): + def getaddr(self): raise NotImplementedError def sort_key(self): @@ -125,6 +128,18 @@ def _clone_if_mutable(self): return self + def get_arg_types(self): + """ Implement in call descr. + Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). + """ + raise NotImplementedError + + def get_return_type(self): + """ Implement in call descr. + Must return INT, REF, FLOAT, or 'v' for void. + """ + raise NotImplementedError + def get_extra_info(self): """ Implement in call descr """ @@ -150,6 +165,12 @@ """ raise NotImplementedError + def as_vtable_size_descr(self): + """ Implement for size descr representing objects with vtables. + Returns self. (it's an annotation hack) + """ + raise NotImplementedError + class AbstractFailDescr(AbstractDescr): index = -1 @@ -176,18 +197,13 @@ __slots__ = () @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): - if not we_are_translated(): - # cannot store integers representing casted addresses - # inside ConstInt() instances that are going through - # translation; must use the special ConstAddr instead. - return ConstAddr(x, cpu) - intval = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) @@ -216,15 +232,13 @@ # to get the other behavior (i.e. using this __eq__). if self.__class__ is not other.__class__: return False - if isinstance(self.value, Symbolic): - v1 = "symbolic", id(self.value) - else: - v1 = self.value - if isinstance(other.value, Symbolic): - v2 = "symbolic", id(other.value) - else: - v2 = other.value - return v1 == v2 + try: + return self.value == other.value + except TypeError: + if (isinstance(self.value, Symbolic) and + isinstance(other.value, Symbolic)): + return self.value is other.value + raise def __ne__(self, other): return not (self == other) @@ -232,6 +246,7 @@ class ConstInt(Const): type = INT + value = 0 _attrs_ = ('value',) def __init__(self, value): @@ -250,11 +265,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -275,50 +290,6 @@ CONST_FALSE = ConstInt(0) CONST_TRUE = ConstInt(1) -class ConstAddr(Const): # only for constants built before translation - type = INT - _attrs_ = ('value', 'cpu') - - def __init__(self, adrvalue, cpu): - "NOT_RPYTHON" - assert not we_are_translated() - if isinstance(lltype.typeOf(adrvalue), lltype.Ptr): - adrvalue = llmemory.cast_ptr_to_adr(adrvalue) # convenience - else: - assert lltype.typeOf(adrvalue) == llmemory.Address - self.value = adrvalue - self.cpu = cpu - - def clonebox(self): - return BoxInt(self.cpu.cast_adr_to_int(self.value)) - - nonconstbox = clonebox - - def getint(self): - return self.cpu.cast_adr_to_int(self.value) - - def getaddr(self, cpu): - return self.value - - def _get_hash_(self): - return llmemory.cast_adr_to_int(self.value) - - def set_future_value(self, cpu, j): - cpu.set_future_value_int(j, self.getint()) - - def same_constant(self, other): - assert isinstance(other, Const) - return self.value == other.getaddr(self.cpu) - - def nonnull(self): - return bool(self.value) - - def _getrepr_(self): - return self.value - - def repr_rpython(self): - return repr_rpython(self, 'ca') - class ConstFloat(Const): type = FLOAT value = 0.0 @@ -355,6 +326,8 @@ def repr_rpython(self): return repr_rpython(self, 'cf') +CONST_FZERO = ConstFloat(0.0) + class ConstPtr(Const): type = REF value = lltype.nullptr(llmemory.GCREF.TO) @@ -382,7 +355,7 @@ else: return 0 - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def set_future_value(self, cpu, j): @@ -403,7 +376,13 @@ def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr - return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) + try: + return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), + self.value)) + except lltype.UninitializedMemoryAccess: + return '' + +CONST_NULL = ConstPtr(ConstPtr.value) class ConstObj(Const): type = REF @@ -435,7 +414,7 @@ def set_future_value(self, cpu, j): cpu.set_future_value_ref(j, self.value) -## def getaddr(self, cpu): +## def getaddr(self): ## # so far this is used only when calling ## # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a ## # real addr, but just a key for the dictionary @@ -464,7 +443,7 @@ is_box = True # hint that we want to make links in graphviz from this @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": @@ -527,11 +506,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -598,7 +577,7 @@ return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def _get_hash_(self): @@ -694,6 +673,13 @@ except lltype.DelayedPointer: return -2 # xxx risk of changing hash... +def make_hashable_int(i): + if not we_are_translated() and isinstance(i, llmemory.AddressAsInt): + # Warning: such a hash changes at the time of translation + adr = heaptracker.int2adr(i) + return llmemory.cast_adr_to_int(adr, "emulated") + return i + # ____________________________________________________________ # The TreeLoop class contains a loop or a generalized loop, i.e. a tree @@ -845,16 +831,6 @@ op = ResOperation(opnum, argboxes, resbox, descr) self.operations[position] = op - def slice_history_at(self, position): - """ a strange function that does this: - history : operation_at_position : rest - it'll kill operation_at_position, store everything before that - in history.operations and return rest - """ - rest = self.operations[position + 1:] - del self.operations[position:] - return rest - # ____________________________________________________________ Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/jitprof.py Fri Jun 18 20:55:39 2010 @@ -5,6 +5,7 @@ import os import time from pypy.rlib.debug import debug_print +from pypy.jit.metainterp.jitexc import JitException counters=""" TRACING @@ -13,7 +14,6 @@ BLACKHOLE OPS RECORDED_OPS -BLACKHOLED_OPS GUARDS OPT_OPS OPT_GUARDS @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 5 # one for TOTAL, 5 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 1 # one for TOTAL, 1 for calls, update if needed class BaseProfiler(object): pass @@ -88,7 +88,7 @@ t1 = 0 times = None counters = None - calls = None + calls = 0 current = None printing = True @@ -97,7 +97,7 @@ self.t1 = self.starttime self.times = [0, 0] self.counters = [0] * ncounters - self.calls = [[0, 0], [0, 0], [0, 0]] + self.calls = 0 self.current = [] def finish(self): @@ -150,10 +150,8 @@ def count_ops(self, opnum, kind=OPS): from pypy.jit.metainterp.resoperation import rop self.counters[kind] += 1 - if opnum == rop.CALL or opnum == rop.OOSEND: - self.calls[kind-OPS][0] += 1 - elif opnum == rop.CALL_PURE or opnum == rop.OOSEND_PURE: - self.calls[kind-OPS][1] += 1 + if opnum == rop.CALL and kind == RECORDED_OPS:# or opnum == rop.OOSEND: + self.calls += 1 def print_stats(self): cnt = self.counters @@ -166,14 +164,9 @@ line = "TOTAL: \t\t%f\n" % (self.tk - self.starttime, ) os.write(2, line) self._print_intline("ops", cnt[OPS]) - self._print_intline(" calls", calls[0][0]) - self._print_intline(" pure calls", calls[0][1]) self._print_intline("recorded ops", cnt[RECORDED_OPS]) - self._print_intline(" calls", calls[1][0]) - self._print_intline(" pure calls", calls[1][1]) + self._print_intline(" calls", calls) self._print_intline("guards", cnt[GUARDS]) - self._print_intline("blackholed ops", calls[2][0]) - self._print_intline(" pure calls", calls[2][1]) self._print_intline("opt ops", cnt[OPT_OPS]) self._print_intline("opt guards", cnt[OPT_GUARDS]) self._print_intline("forcings", cnt[OPT_FORCINGS]) @@ -195,5 +188,5 @@ -class BrokenProfilerData(Exception): +class BrokenProfilerData(JitException): pass Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/logger.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/logger.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/logger.py Fri Jun 18 20:55:39 2010 @@ -1,9 +1,11 @@ import os from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, \ - BoxInt, ConstAddr, ConstFloat, BoxFloat, AbstractFailDescr + BoxInt, ConstFloat, BoxFloat, AbstractFailDescr class Logger(object): @@ -46,10 +48,16 @@ mv = len(memo) memo[arg] = mv if isinstance(arg, ConstInt): + if int_could_be_an_address(arg.value): + addr = arg.getaddr() + name = self.metainterp_sd.get_name_from_address(addr) + if name: + return 'ConstClass(' + name + ')' return str(arg.value) elif isinstance(arg, BoxInt): return 'i' + str(mv) elif isinstance(arg, self.ts.ConstRef): + # XXX for ootype, this should also go through get_name_from_address return 'ConstPtr(ptr' + str(mv) + ')' elif isinstance(arg, self.ts.BoxRef): return 'p' + str(mv) @@ -57,12 +65,6 @@ return str(arg.value) elif isinstance(arg, BoxFloat): return 'f' + str(mv) - elif isinstance(arg, self.ts.ConstAddr): - addr = arg.getaddr(self.metainterp_sd.cpu) - name = self.metainterp_sd.get_name_from_address(addr) - if not name: - name = 'cls' + str(mv) - return 'ConstClass(' + name + ')' elif arg is None: return 'None' else: @@ -102,3 +104,11 @@ fail_args = '' debug_print(res + op.getopname() + '(' + args + ')' + fail_args) + + +def int_could_be_an_address(x): + if we_are_translated(): + x = rffi.cast(lltype.Signed, x) # force it + return not (-32768 <= x <= 32767) + else: + return isinstance(x, llmemory.AddressAsInt) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizefindnode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizefindnode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizefindnode.py Fri Jun 18 20:55:39 2010 @@ -160,7 +160,8 @@ else: # all constant arguments: we can constant-fold argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.set_constant_node(op.result, resbox.constbox()) # default case: mark the arguments as escaping for box in op.args: @@ -169,8 +170,8 @@ def find_nodes_no_escape(self, op): pass # for operations that don't escape their arguments - find_nodes_OOIS = find_nodes_no_escape - find_nodes_OOISNOT = find_nodes_no_escape + find_nodes_PTR_EQ = find_nodes_no_escape + find_nodes_PTR_NE = find_nodes_no_escape find_nodes_INSTANCEOF = find_nodes_no_escape find_nodes_GUARD_NONNULL = find_nodes_no_escape find_nodes_GUARD_ISNULL = find_nodes_no_escape Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py Fri Jun 18 20:55:39 2010 @@ -16,7 +16,7 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype -from pypy.jit.metainterp.history import AbstractDescr +from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int def optimize_loop_1(metainterp_sd, loop): """Optimize loop.operations to make it match the input of loop.specnodes @@ -89,7 +89,7 @@ if level == LEVEL_KNOWNCLASS: return self.known_class elif level == LEVEL_CONSTANT: - return cpu.ts.cls_of_box(cpu, self.box) + return cpu.ts.cls_of_box(self.box) else: return None @@ -564,7 +564,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) newboxes = modifier.finish(self.values, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here - raise compile.GiveUp + compile.giveup() descr.store_final_boxes(op, newboxes) # if op.opnum == rop.GUARD_VALUE: @@ -594,7 +594,8 @@ else: # all constant arguments: constant-fold away argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.make_constant(op.result, resbox.constbox()) return @@ -747,6 +748,9 @@ def optimize_INT_IS_TRUE(self, op): self._optimize_nullness(op, op.args[0], True) + def optimize_INT_IS_ZERO(self, op): + self._optimize_nullness(op, op.args[0], False) + def _optimize_oois_ooisnot(self, op, expect_isnot): value0 = self.getvalue(op.args[0]) value1 = self.getvalue(op.args[1]) @@ -775,10 +779,10 @@ return self.optimize_default(op) - def optimize_OOISNOT(self, op): + def optimize_PTR_NE(self, op): self._optimize_oois_ooisnot(op, True) - def optimize_OOIS(self, op): + def optimize_PTR_EQ(self, op): self._optimize_oois_ooisnot(op, False) def optimize_VIRTUAL_REF(self, op): @@ -944,7 +948,8 @@ if not funcvalue.is_constant(): self.optimize_default(op) return - resvalue = self.loop_invariant_results.get(op.args[0].getint(), None) + key = make_hashable_int(op.args[0].getint()) + resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: self.make_equal_to(op.result, resvalue) return @@ -953,7 +958,19 @@ op.opnum = rop.CALL self.optimize_default(op) resvalue = self.getvalue(op.result) - self.loop_invariant_results[op.args[0].getint()] = resvalue + self.loop_invariant_results[key] = resvalue + + def optimize_CALL_PURE(self, op): + for arg in op.args: + if self.get_constant_box(arg) is None: + break + else: + # all constant arguments: constant-fold away + self.make_constant(op.result, op.args[0]) + return + # replace CALL_PURE with just CALL + self.emit_operation(ResOperation(rop.CALL, op.args[1:], op.result, + op.descr)) def optimize_INT_AND(self, op): v1 = self.getvalue(op.args[0]) @@ -1077,6 +1094,7 @@ opnum == rop.SETARRAYITEM_GC or opnum == rop.DEBUG_MERGE_POINT): return + assert opnum != rop.CALL_PURE if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or opnum == rop.CALL_ASSEMBLER): @@ -1100,7 +1118,7 @@ del self.cached_arrayitems[arraydescr] except KeyError: pass - if effectinfo.forces_virtual_or_virtualizable: + if effectinfo.check_forces_virtual_or_virtualizable(): vrefinfo = self.optimizer.metainterp_sd.virtualref_info self.force_lazy_setfield(vrefinfo.descr_forced) # ^^^ we only need to force this field; the other fields Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeutil.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeutil.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeutil.py Fri Jun 18 20:55:39 2010 @@ -2,8 +2,9 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp import resoperation, history +from pypy.jit.metainterp.jitexc import JitException -class InvalidLoop(Exception): +class InvalidLoop(JitException): """Raised when the optimize*.py detect that the loop that we are trying to build cannot possibly make sense as a long-running loop (e.g. it cannot run 2 complete iterations).""" Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/pyjitpl.py Fri Jun 18 20:55:39 2010 @@ -1,205 +1,170 @@ import py, os -from pypy.rpython.lltypesystem import llmemory -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.debug import make_sure_not_resized +from pypy.rlib import nonconst from pypy.jit.metainterp import history, compile, resume -from pypy.jit.metainterp.history import Const, ConstInt, Box +from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat +from pypy.jit.metainterp.history import Box from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp import codewriter, executor +from pypy.jit.metainterp import executor from pypy.jit.metainterp.logger import Logger -from pypy.jit.metainterp.jitprof import BLACKHOLED_OPS, EmptyProfiler +from pypy.jit.metainterp.jitprof import EmptyProfiler from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE +from pypy.jit.metainterp.jitexc import JitException, get_llexception from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED -from pypy.jit.metainterp.compile import GiveUp +from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ -def check_args(*args): - for arg in args: - assert isinstance(arg, (Box, Const)) - -class arguments(object): - def __init__(self, *argtypes): - self.argtypes = argtypes - - def __eq__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes == other.argtypes - - def __ne__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes != other.argtypes - - def __call__(self, func): - argtypes = unrolling_iterable(self.argtypes) - def wrapped(self, orgpc): - args = (self, ) - for argspec in argtypes: - if argspec == "box": - box = self.load_arg() - args += (box, ) - elif argspec == "constbox": - args += (self.load_const_arg(), ) - elif argspec == "int": - args += (self.load_int(), ) - elif argspec == "jumptarget": - args += (self.load_3byte(), ) - elif argspec == "jumptargets": - num = self.load_int() - args += ([self.load_3byte() for i in range(num)], ) - elif argspec == "varargs": - args += (self.load_varargs(), ) - elif argspec == "constargs": - args += (self.load_constargs(), ) - elif argspec == "descr": - descr = self.load_const_arg() - assert isinstance(descr, history.AbstractDescr) - args += (descr, ) - elif argspec == "bytecode": - bytecode = self.load_const_arg() - assert isinstance(bytecode, codewriter.JitCode) - args += (bytecode, ) - elif argspec == "orgpc": - args += (orgpc, ) - elif argspec == "methdescr": - methdescr = self.load_const_arg() - assert isinstance(methdescr, - history.AbstractMethDescr) - args += (methdescr, ) - else: - assert 0, "unknown argtype declaration: %r" % (argspec,) - val = func(*args) - if val is None: - val = False - return val - name = func.func_name - wrapped.func_name = "wrap_" + name - wrapped.argspec = self - return wrapped +def arguments(*args): + def decorate(func): + func.argtypes = args + return func + return decorate # ____________________________________________________________ class MIFrame(object): - exception_box = None - exc_value_box = None - # for resume.py operation - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - def __init__(self, metainterp, jitcode, greenkey=None): - assert isinstance(jitcode, codewriter.JitCode) + def __init__(self, metainterp): self.metainterp = metainterp + self.registers_i = [None] * 256 + self.registers_r = [None] * 256 + self.registers_f = [None] * 256 + + def setup(self, jitcode, greenkey=None): + assert isinstance(jitcode, JitCode) self.jitcode = jitcode self.bytecode = jitcode.code - self.constants = jitcode.constants - self.exception_target = -1 - self.name = jitcode.name # purely for having name attribute # this is not None for frames that are recursive portal calls self.greenkey = greenkey + # copy the constants in place + self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt) + self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr) + self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat) + self._result_argcode = 'v' + # for resume.py operation + self.parent_resumedata_snapshot = None + self.parent_resumedata_frame_info_list = None + + def copy_constants(self, registers, constants, ConstClass): + """Copy jitcode.constants[0] to registers[255], + jitcode.constants[1] to registers[254], + jitcode.constants[2] to registers[253], etc.""" + if nonconst.NonConstant(0): # force the right type + constants[0] = ConstClass.value # (useful for small tests) + i = len(constants) - 1 + while i >= 0: + j = 255 - i + assert j >= 0 + registers[j] = ConstClass(constants[i]) + i -= 1 + copy_constants._annspecialcase_ = 'specialize:arg(3)' + + def cleanup_registers(self): + # To avoid keeping references alive, this cleans up the registers_r. + # It does not clear the references set by copy_constants(), but + # these are all prebuilt constants anyway. + for i in range(self.jitcode.num_regs_r()): + self.registers_r[i] = None # ------------------------------ # Decoding of the JitCode - def load_int(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - if result > 0x7F: - result = self._load_larger_int(result) - return result - - def _load_larger_int(self, result): # slow path - result = result & 0x7F - shift = 7 - pc = self.pc - while 1: - byte = ord(self.bytecode[pc]) - pc += 1 - result += (byte & 0x7F) << shift - shift += 7 - if not byte & 0x80: - break - self.pc = pc - return intmask(result) - _load_larger_int._dont_inline_ = True - - def load_3byte(self): - pc = self.pc - result = (((ord(self.bytecode[pc + 0])) << 16) | - ((ord(self.bytecode[pc + 1])) << 8) | - ((ord(self.bytecode[pc + 2])) << 0)) - self.pc = pc + 3 - return result - - def load_bool(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - return bool(result) - - def getenv(self, i): - assert i >= 0 - j = i >> 1 - if i & 1: - return self.constants[j] - else: - assert j < len(self.env) - return self.env[j] - - def load_arg(self): - return self.getenv(self.load_int()) - - def load_const_arg(self): - return self.constants[self.load_int()] - - def load_varargs(self): - count = self.load_int() - return [self.load_arg() for i in range(count)] - - def load_constargs(self): - count = self.load_int() - return [self.load_const_arg() for i in range(count)] - - def ignore_varargs(self): - count = self.load_int() + def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): + assert argcode in 'IRF' + code = self.bytecode + length = ord(code[position]) + position += 1 + for i in range(length): + index = ord(code[position+i]) + if argcode == 'I': reg = self.registers_i[index] + elif argcode == 'R': reg = self.registers_r[index] + elif argcode == 'F': reg = self.registers_f[index] + else: raise AssertionError(argcode) + outvalue[startindex+i] = reg + prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' + + def get_current_position_info(self): + return self.jitcode.get_live_vars_info(self.pc) + + def get_list_of_active_boxes(self, in_a_call): + if in_a_call: + # If we are not the topmost frame, self._result_argcode contains + # the type of the result of the call instruction in the bytecode. + # We use it to clear the box that will hold the result: this box + # is not defined yet. + argcode = self._result_argcode + index = ord(self.bytecode[self.pc - 1]) + if argcode == 'i': self.registers_i[index] = history.CONST_FALSE + elif argcode == 'r': self.registers_r[index] = history.CONST_NULL + elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO + self._result_argcode = '?' # done + # + info = self.get_current_position_info() + start_i = 0 + start_r = start_i + info.get_register_count_i() + start_f = start_r + info.get_register_count_r() + total = start_f + info.get_register_count_f() + # allocate a list of the correct size + env = [None] * total + make_sure_not_resized(env) + # fill it now + for i in range(info.get_register_count_i()): + index = info.get_register_index_i(i) + env[start_i + i] = self.registers_i[index] + for i in range(info.get_register_count_r()): + index = info.get_register_index_r(i) + env[start_r + i] = self.registers_r[index] + for i in range(info.get_register_count_f()): + index = info.get_register_index_f(i) + env[start_f + i] = self.registers_f[index] + return env + + def replace_active_box_in_frame(self, oldbox, newbox): + if isinstance(oldbox, history.BoxInt): + count = self.jitcode.num_regs_i() + registers = self.registers_i + elif isinstance(oldbox, history.BoxPtr): + count = self.jitcode.num_regs_r() + registers = self.registers_r + elif isinstance(oldbox, history.BoxFloat): + count = self.jitcode.num_regs_f() + registers = self.registers_f + else: + assert 0, oldbox for i in range(count): - self.load_int() - - def getvarenv(self, i): - return self.env[i] + if registers[i] is oldbox: + registers[i] = newbox + if not we_are_translated(): + assert oldbox not in registers[count:] - def make_result_box(self, box): - assert isinstance(box, Box) or isinstance(box, Const) - self.env.append(box) + def make_result_of_lastop(self, resultbox): + if resultbox is None: + return + target_index = ord(self.bytecode[self.pc-1]) + if resultbox.type == history.INT: + self.registers_i[target_index] = resultbox + elif resultbox.type == history.REF: + #debug_print(' ->', + # llmemory.cast_ptr_to_adr(resultbox.getref_base())) + self.registers_r[target_index] = resultbox + elif resultbox.type == history.FLOAT: + self.registers_f[target_index] = resultbox + else: + raise AssertionError("bad result box type") # ------------------------------ - for _n in range(codewriter.MAX_MAKE_NEW_VARS): - _decl = ', '.join(["'box'" for _i in range(_n)]) - _allargs = ', '.join(["box%d" % _i for _i in range(_n)]) - exec py.code.Source(""" - @arguments(%s) - def opimpl_make_new_vars_%d(self, %s): - if not we_are_translated(): - check_args(%s) - self.env = [%s] - """ % (_decl, _n, _allargs, _allargs, _allargs)).compile() - - @arguments("varargs") - def opimpl_make_new_vars(self, newenv): - if not we_are_translated(): - check_args(*newenv) - self.env = newenv - for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod', 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', @@ -210,175 +175,251 @@ 'float_add', 'float_sub', 'float_mul', 'float_truediv', 'float_lt', 'float_le', 'float_eq', 'float_ne', 'float_gt', 'float_ge', + 'ptr_eq', 'ptr_ne', ]: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) + return self.execute(rop.%s, b1, b2) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) - return self.metainterp.handle_overflow_error() + self.metainterp.clear_exception() + resbox = self.execute(rop.%s, b1, b2) + self.make_result_of_lastop(resbox) # same as execute_varargs() + self.metainterp.handle_possible_overflow_error() + return resbox ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', - 'cast_ptr_to_int', 'cast_float_to_int', - 'cast_int_to_float', 'float_neg', 'float_abs', - 'float_is_true', + for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert', + 'cast_float_to_int', 'cast_int_to_float', + 'float_neg', 'float_abs', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, b) + return self.execute(rop.%s, b) ''' % (_opimpl, _opimpl.upper())).compile() - @arguments() - def opimpl_return(self): - assert len(self.env) == 1 - return self.metainterp.finishframe(self.env[0]) + @arguments("box") + def opimpl_ptr_nonzero(self, box): + return self.execute(rop.PTR_NE, box, history.CONST_NULL) + + @arguments("box") + def opimpl_ptr_iszero(self, box): + return self.execute(rop.PTR_EQ, box, history.CONST_NULL) + + @arguments("box") + def _opimpl_any_return(self, box): + self.metainterp.finishframe(box) + + opimpl_int_return = _opimpl_any_return + opimpl_ref_return = _opimpl_any_return + opimpl_float_return = _opimpl_any_return @arguments() def opimpl_void_return(self): - assert len(self.env) == 0 - return self.metainterp.finishframe(None) + self.metainterp.finishframe(None) + + @arguments("box") + def _opimpl_any_copy(self, box): + return box + + opimpl_int_copy = _opimpl_any_copy + opimpl_ref_copy = _opimpl_any_copy + opimpl_float_copy = _opimpl_any_copy + + @arguments("box") + def _opimpl_any_push(self, box): + self.pushed_box = box + + opimpl_int_push = _opimpl_any_push + opimpl_ref_push = _opimpl_any_push + opimpl_float_push = _opimpl_any_push - @arguments("jumptarget") + @arguments() + def _opimpl_any_pop(self): + box = self.pushed_box + self.pushed_box = None + return box + + opimpl_int_pop = _opimpl_any_pop + opimpl_ref_pop = _opimpl_any_pop + opimpl_float_pop = _opimpl_any_pop + + @arguments("label") + def opimpl_catch_exception(self, target): + """This is a no-op when run normally. We can check that + last_exc_value_box is None; it should have been set to None + by the previous instruction. If the previous instruction + raised instead, finishframe_exception() should have been + called and we would not be there.""" + assert self.metainterp.last_exc_value_box is None + + @arguments("label") def opimpl_goto(self, target): self.pc = target - @arguments("orgpc", "jumptarget", "box", "varargs") - def opimpl_goto_if_not(self, pc, target, box, livelist): + @arguments("box", "label") + def opimpl_goto_if_not(self, box, target): switchcase = box.getint() if switchcase: opnum = rop.GUARD_TRUE else: - self.pc = target opnum = rop.GUARD_FALSE - self.env = livelist - self.generate_guard(pc, opnum, box) - # note about handling self.env explicitly here: it is done in - # such a way that the 'box' on which we generate the guard is - # typically not included in the livelist. - - def follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - target = self.load_3byte() # load the 'target' argument - self.pc = target # jump - - def ignore_next_guard_nullness(self, opnum): - _op_ooisnull = self.metainterp.staticdata._op_ooisnull - _op_oononnull = self.metainterp.staticdata._op_oononnull - bc = ord(self.bytecode[self.pc]) - if bc == _op_ooisnull: - if opnum == rop.GUARD_ISNULL: - res = ConstInt(0) - else: - res = ConstInt(1) + self.generate_guard(opnum, box) + if not switchcase: + self.pc = target + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_true(self, box, target): + condbox = self.execute(rop.INT_IS_TRUE, box) + self.opimpl_goto_if_not(condbox, target) + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_zero(self, box, target): + condbox = self.execute(rop.INT_IS_ZERO, box) + self.opimpl_goto_if_not(condbox, target) + + for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', + 'ptr_eq', 'ptr_ne']: + exec py.code.Source(''' + @arguments("box", "box", "label") + def opimpl_goto_if_not_%s(self, b1, b2, target): + condbox = self.execute(rop.%s, b1, b2) + self.opimpl_goto_if_not(condbox, target) + ''' % (_opimpl, _opimpl.upper())).compile() + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL else: - assert bc == _op_oononnull - if opnum == rop.GUARD_ISNULL: - res = ConstInt(1) - else: - res = ConstInt(0) - self.pc += 1 # past the bytecode for ptr_iszero/ptr_nonzero - self.load_int() # past the 'box' argument - self.make_result_box(res) - - def dont_follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - self.load_3byte() # past the 'target' argument - self.load_int() # past the 'box' argument - self.ignore_varargs() # past the 'livelist' argument - - @arguments("orgpc", "box", "constargs", "jumptargets") - def opimpl_switch(self, pc, valuebox, constargs, jumptargets): - box = self.implement_guard_value(pc, valuebox) - for i in range(len(constargs)): - casebox = constargs[i] - if box.same_constant(casebox): - self.pc = jumptargets[i] - break + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if not value: + self.pc = target - @arguments("orgpc", "box", "constbox") - def opimpl_switch_dict(self, pc, valuebox, switchdict): - box = self.implement_guard_value(pc, valuebox) + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL + else: + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if value: + self.pc = target + + @arguments("box", "box", "box") + def opimpl_int_between(self, b1, b2, b3): + b5 = self.execute(rop.INT_SUB, b3, b1) + if isinstance(b5, ConstInt) and b5.getint() == 1: + # the common case of int_between(a, b, a+1) turns into just INT_EQ + return self.execute(rop.INT_EQ, b2, b1) + else: + b4 = self.execute(rop.INT_SUB, b2, b1) + return self.execute(rop.UINT_LT, b4, b5) + + @arguments("box", "descr", "orgpc") + def opimpl_switch(self, valuebox, switchdict, orgpc): + box = self.implement_guard_value(orgpc, valuebox) search_value = box.getint() - assert isinstance(switchdict, codewriter.SwitchDict) + assert isinstance(switchdict, SwitchDictDescr) try: self.pc = switchdict.dict[search_value] except KeyError: pass - @arguments("descr") - def opimpl_new(self, size): - self.execute_with_descr(rop.NEW, descr=size) - - @arguments("constbox") - def opimpl_new_with_vtable(self, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, vtablebox) + @arguments() + def opimpl_unreachable(self): + raise AssertionError("unreachable") - @arguments("box") - def opimpl_runtimenew(self, classbox): - self.execute(rop.RUNTIMENEW, classbox) + @arguments("descr") + def opimpl_new(self, sizedescr): + return self.execute_with_descr(rop.NEW, sizedescr) - @arguments("orgpc", "box", "descr") - def opimpl_instanceof(self, pc, objbox, typedescr): - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + @arguments("descr") + def opimpl_new_with_vtable(self, sizedescr): + cpu = self.metainterp.cpu + cls = heaptracker.descr2vtable(cpu, sizedescr) + return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls)) - @arguments("box", "box") - def opimpl_subclassof(self, box1, box2): - self.execute(rop.SUBCLASSOF, box1, box2) +## @FixME #arguments("box") +## def opimpl_runtimenew(self, classbox): +## self.execute(rop.RUNTIMENEW, classbox) + +## @FixME #arguments("orgpc", "box", "descr") +## def opimpl_instanceof(self, pc, objbox, typedescr): +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + +## @FixME #arguments("box", "box") +## def opimpl_subclassof(self, box1, box2): +## self.execute(rop.SUBCLASSOF, box1, box2) @arguments("descr", "box") - def opimpl_new_array(self, itemsize, countbox): - self.execute_with_descr(rop.NEW_ARRAY, itemsize, countbox) + def opimpl_new_array(self, itemsizedescr, countbox): + return self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, countbox) @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_pure_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_pure_i = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_r = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_f = _opimpl_getarrayitem_gc_pure_any @arguments("box", "descr", "box", "box") - def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydesc, arraybox, indexbox, itembox) + def _opimpl_setarrayitem_gc_any(self, arraybox, arraydescr, + indexbox, itembox): + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, itembox) + + opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any @arguments("box", "descr") - def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute_with_descr(rop.ARRAYLEN_GC, arraydesc, arraybox) + def opimpl_arraylen_gc(self, arraybox, arraydescr): + return self.execute_with_descr(rop.ARRAYLEN_GC, arraydescr, arraybox) @arguments("descr", "box", "box", "box", "box", "box", "box", "descr") def opimpl_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): + source_startbox, dest_startbox, lengthbox, + arraydescr): self.execute_with_descr(rop.ARRAYCOPY, arraydescr, calldescr, fnptr, sourcebox, destbox, source_startbox, dest_startbox, lengthbox) @arguments("orgpc", "box", "descr", "box") - def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): + def opimpl_check_neg_index(self, orgpc, arraybox, arraydescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, arraydesc, arraybox) + rop.ARRAYLEN_GC, arraydescr, arraybox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) + return indexbox @arguments("descr", "descr", "descr", "descr", "box") def opimpl_newlist(self, structdescr, lengthdescr, itemsdescr, arraydescr, @@ -390,131 +431,87 @@ sizebox) self.metainterp.execute_and_record(rop.SETFIELD_GC, itemsdescr, sbox, abox) - self.make_result_box(sbox) + return sbox @arguments("box", "descr", "descr", "box") - def opimpl_getlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox): + def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydescr, arraybox, indexbox) + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any @arguments("box", "descr", "descr", "box", "box") - def opimpl_setlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox, - valuebox): + def _opimpl_setlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox, valuebox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, indexbox, valuebox) + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, valuebox) + + opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any @arguments("orgpc", "box", "descr", "box") - def opimpl_check_resizable_neg_index(self, pc, listbox, lengthdesc, + def opimpl_check_resizable_neg_index(self, orgpc, listbox, lengthdescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.GETFIELD_GC, lengthdesc, listbox) + rop.GETFIELD_GC, lengthdescr, listbox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) - - @arguments("orgpc", "box") - def opimpl_check_zerodivisionerror(self, pc, box): - nonzerobox = self.metainterp.execute_and_record( - rop.INT_NE, None, box, ConstInt(0)) - nonzerobox = self.implement_guard_value(pc, nonzerobox) - if nonzerobox.getint(): - return False - else: - # division by zero! - return self.metainterp.raise_zero_division_error() - - @arguments("orgpc", "box", "box") - def opimpl_check_div_overflow(self, pc, box1, box2): - # detect the combination "box1 = -sys.maxint-1, box2 = -1". - import sys - tmp1 = self.metainterp.execute_and_record( # combination to detect: - rop.INT_ADD, None, box1, ConstInt(sys.maxint)) # tmp1=-1, box2=-1 - tmp2 = self.metainterp.execute_and_record( - rop.INT_AND, None, tmp1, box2) # tmp2=-1 - tmp3 = self.metainterp.execute_and_record( - rop.INT_EQ, None, tmp2, ConstInt(-1)) # tmp3? - tmp4 = self.implement_guard_value(pc, tmp3) # tmp4? - if not tmp4.getint(): - return False - else: - # division overflow! - return self.metainterp.raise_overflow_error() - - @arguments() - def opimpl_overflow_error(self): - return self.metainterp.raise_overflow_error() - - @arguments("orgpc", "box") - def opimpl_int_abs(self, pc, box): - nonneg = self.metainterp.execute_and_record( - rop.INT_GE, None, box, ConstInt(0)) - nonneg = self.implement_guard_value(pc, nonneg) - if nonneg.getint(): - self.make_result_box(box) - else: - self.execute(rop.INT_NEG, box) - - @arguments("orgpc", "box") - def opimpl_oononnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(1) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(0) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("orgpc", "box") - def opimpl_ooisnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(0) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(1) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("box", "box") - def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, box1, box2) - - @arguments("box", "box") - def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, box1, box2) - - opimpl_oois = opimpl_ptr_eq - opimpl_ooisnot = opimpl_ptr_ne + return indexbox @arguments("box", "descr") - def opimpl_getfield_gc(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC, fielddesc, box) + def _opimpl_getfield_gc_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) + opimpl_getfield_gc_i = _opimpl_getfield_gc_any + opimpl_getfield_gc_r = _opimpl_getfield_gc_any + opimpl_getfield_gc_f = _opimpl_getfield_gc_any + @arguments("box", "descr") - def opimpl_getfield_gc_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddesc, box) + def _opimpl_getfield_gc_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box) + opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_GC, fielddesc, box, valuebox) + def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) + opimpl_setfield_gc_i = _opimpl_setfield_gc_any + opimpl_setfield_gc_r = _opimpl_setfield_gc_any + opimpl_setfield_gc_f = _opimpl_setfield_gc_any @arguments("box", "descr") - def opimpl_getfield_raw(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW, fielddesc, box) + def _opimpl_getfield_raw_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box) + opimpl_getfield_raw_i = _opimpl_getfield_raw_any + opimpl_getfield_raw_r = _opimpl_getfield_raw_any + opimpl_getfield_raw_f = _opimpl_getfield_raw_any + @arguments("box", "descr") - def opimpl_getfield_raw_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddesc, box) + def _opimpl_getfield_raw_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box) + opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_RAW, fielddesc, box, valuebox) + def _opimpl_setfield_raw_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox) + opimpl_setfield_raw_i = _opimpl_setfield_raw_any + opimpl_setfield_raw_r = _opimpl_setfield_raw_any + opimpl_setfield_raw_f = _opimpl_setfield_raw_any def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable @@ -522,7 +519,7 @@ standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False - eqbox = self.metainterp.execute_and_record(rop.OOIS, None, + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, box, standard_box) eqbox = self.implement_guard_value(pc, eqbox) isstandard = eqbox.getint() @@ -530,9 +527,9 @@ self.metainterp.replace_box(box, standard_box) return not isstandard - def _get_virtualizable_field_descr(self, index): + def _get_virtualizable_field_index(self, fielddescr): vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.static_field_descrs[index] + return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): vinfo = self.metainterp.staticdata.virtualizable_info @@ -542,328 +539,271 @@ vinfo = self.metainterp.staticdata.virtualizable_info return vinfo.array_descrs[index] - @arguments("orgpc", "box", "int") - def opimpl_getfield_vable(self, pc, basebox, index): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.GETFIELD_GC, self._get_virtualizable_field_descr(index), basebox) - return + @arguments("orgpc", "box", "descr") + def _opimpl_getfield_vable(self, pc, box, fielddescr): + if self._nonstandard_virtualizable(pc, box): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) self.metainterp.check_synchronized_virtualizable() - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box") - def opimpl_setfield_vable(self, pc, basebox, index, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.SETFIELD_GC, self._get_virtualizable_field_descr(index), basebox, valuebox) + index = self._get_virtualizable_field_index(fielddescr) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getfield_vable_i = _opimpl_getfield_vable + opimpl_getfield_vable_r = _opimpl_getfield_vable + opimpl_getfield_vable_f = _opimpl_getfield_vable + + @arguments("orgpc", "box", "descr", "box") + def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox): + if self._nonstandard_virtualizable(pc, box): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) return + index = self._get_virtualizable_field_index(fielddescr) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - def _get_arrayitem_vable_index(self, pc, arrayindex, indexbox): + opimpl_setfield_vable_i = _opimpl_setfield_vable + opimpl_setfield_vable_r = _opimpl_setfield_vable + opimpl_setfield_vable_f = _opimpl_setfield_vable + + def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] index = indexbox.getint() if index < 0: index += vinfo.get_array_length(virtualizable, arrayindex) assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex) return vinfo.get_index_in_array(virtualizable, arrayindex, index) - @arguments("orgpc", "box", "int", "box") - def opimpl_getarrayitem_vable(self, pc, basebox, arrayindex, indexbox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + @arguments("orgpc", "box", "descr", "descr", "box") + def _opimpl_getarrayitem_vable(self, pc, box, fdescr, adescr, indexbox): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.GETARRAYITEM_GC, descr, - arraybox, indexbox) - return + fdescr, box) + return self.execute_with_descr(rop.GETARRAYITEM_GC, adescr, + arraybox, indexbox) self.metainterp.check_synchronized_virtualizable() - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box", "box") - def opimpl_setarrayitem_vable(self, pc, basebox, arrayindex, indexbox, + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr", "box", "box") + def _opimpl_setarrayitem_vable(self, pc, box, fdescr, adescr, indexbox, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.SETARRAYITEM_GC, descr, + fdescr, box) + self.execute_with_descr(rop.SETARRAYITEM_GC, adescr, arraybox, indexbox, valuebox) return - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - @arguments("orgpc", "box", "int") - def opimpl_arraylen_vable(self, pc, basebox, arrayindex): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + + opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr") + def opimpl_arraylen_vable(self, pc, box, fdescr, adescr): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.ARRAYLEN_GC, descr, arraybox) - return + fdescr, box) + return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[fdescr] result = vinfo.get_array_length(virtualizable, arrayindex) - self.make_result_box(ConstInt(result)) + return ConstInt(result) - def perform_call(self, jitcode, varargs, greenkey=None): - if (self.metainterp.is_blackholing() and - jitcode.calldescr is not None): - # when producing only a BlackHole, we can implement this by - # calling the subfunction directly instead of interpreting it - if jitcode.cfnptr is not None: - # for non-oosends - varargs = [jitcode.cfnptr] + varargs - res = self.execute_varargs(rop.CALL, varargs, - descr=jitcode.calldescr, exc=True) - else: - # for oosends (ootype only): calldescr is a MethDescr - res = self.execute_varargs(rop.OOSEND, varargs, - descr=jitcode.calldescr, exc=True) - self.metainterp.load_fields_from_virtualizable() - return res - else: - # when tracing, this bytecode causes the subfunction to be entered - f = self.metainterp.newframe(jitcode, greenkey) - f.setup_call(varargs) - return True - - @arguments("bytecode", "varargs") - def opimpl_call(self, callee, varargs): - return self.perform_call(callee, varargs) - - @arguments("descr", "varargs") - def opimpl_residual_call(self, calldescr, varargs): - return self.do_residual_call(varargs, descr=calldescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_call_loopinvariant(self, calldescr, varargs): - return self.execute_varargs(rop.CALL_LOOPINVARIANT, varargs, calldescr, exc=True) - - @arguments("orgpc", "descr", "varargs") - def opimpl_recursive_call(self, pc, calldescr, varargs): - warmrunnerstate = self.metainterp.staticdata.state + @arguments("jitcode", "boxes") + def _opimpl_inline_call1(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes2") + def _opimpl_inline_call2(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes3") + def _opimpl_inline_call3(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + + opimpl_inline_call_r_i = _opimpl_inline_call1 + opimpl_inline_call_r_r = _opimpl_inline_call1 + opimpl_inline_call_r_v = _opimpl_inline_call1 + opimpl_inline_call_ir_i = _opimpl_inline_call2 + opimpl_inline_call_ir_r = _opimpl_inline_call2 + opimpl_inline_call_ir_v = _opimpl_inline_call2 + opimpl_inline_call_irf_i = _opimpl_inline_call3 + opimpl_inline_call_irf_r = _opimpl_inline_call3 + opimpl_inline_call_irf_f = _opimpl_inline_call3 + opimpl_inline_call_irf_v = _opimpl_inline_call3 + + @arguments("box", "descr", "boxes") + def _opimpl_residual_call1(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes2") + def _opimpl_residual_call2(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes3") + def _opimpl_residual_call3(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + + opimpl_residual_call_r_i = _opimpl_residual_call1 + opimpl_residual_call_r_r = _opimpl_residual_call1 + opimpl_residual_call_r_v = _opimpl_residual_call1 + opimpl_residual_call_ir_i = _opimpl_residual_call2 + opimpl_residual_call_ir_r = _opimpl_residual_call2 + opimpl_residual_call_ir_v = _opimpl_residual_call2 + opimpl_residual_call_irf_i = _opimpl_residual_call3 + opimpl_residual_call_irf_r = _opimpl_residual_call3 + opimpl_residual_call_irf_f = _opimpl_residual_call3 + opimpl_residual_call_irf_v = _opimpl_residual_call3 + + @arguments("boxes3", "boxes3") + def _opimpl_recursive_call(self, greenboxes, redboxes): + allboxes = greenboxes + redboxes + metainterp_sd = self.metainterp.staticdata + portal_code = metainterp_sd.portal_code + warmrunnerstate = metainterp_sd.state token = None - if not self.metainterp.is_blackholing() and warmrunnerstate.inlining: - num_green_args = self.metainterp.staticdata.num_green_args - portal_code = self.metainterp.staticdata.portal_code - greenkey = varargs[1:num_green_args + 1] - if warmrunnerstate.can_inline_callable(greenkey): - return self.perform_call(portal_code, varargs[1:], greenkey) - token = warmrunnerstate.get_assembler_token(greenkey) - call_position = 0 - if token is not None: - call_position = len(self.metainterp.history.operations) + if warmrunnerstate.inlining: + if warmrunnerstate.can_inline_callable(greenboxes): + return self.metainterp.perform_call(portal_code, allboxes, + greenkey=greenboxes) + token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - greenargs = varargs[1:num_green_args + 1] - self.verify_green_args(greenargs) - res = self.do_residual_call(varargs, descr=calldescr, exc=True) - if not self.metainterp.is_blackholing() and token is not None: - # XXX fix the call position, - found = False - while True: - op = self.metainterp.history.operations[call_position] - if op.opnum == rop.CALL or op.opnum == rop.CALL_MAY_FORCE: - found = True - break - call_position += 1 - assert found - # - # this will substitute the residual call with assembler call - self.metainterp.direct_assembler_call(pc, varargs, token, - call_position) - return res - - @arguments("descr", "varargs") - def opimpl_residual_call_noexception(self, calldescr, varargs): - self.do_residual_call(varargs, descr=calldescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_call_pure(self, calldescr, varargs): - self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False) - - @arguments("orgpc", "descr", "box", "varargs") - def opimpl_indirect_call(self, pc, calldescr, box, varargs): - box = self.implement_guard_value(pc, box) - cpu = self.metainterp.cpu - key = cpu.ts.getaddr_for_box(cpu, box) - jitcode = self.metainterp.staticdata.bytecode_for_address(key) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.do_residual_call([box] + varargs, - descr=calldescr, exc=True) - - @arguments("orgpc", "methdescr", "varargs") - def opimpl_oosend(self, pc, methdescr, varargs): - objbox = varargs[0] - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - oocls = clsbox.getref(ootype.Class) - jitcode = methdescr.get_jitcode_for_class(oocls) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.execute_varargs(rop.OOSEND, varargs, - descr=methdescr, exc=True) + self.verify_green_args(greenboxes) + # + k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + funcbox = ConstInt(heaptracker.adr2int(k)) + return self.do_residual_call(funcbox, portal_code.calldescr, + allboxes, assembler_call_token=token) + + opimpl_recursive_call_i = _opimpl_recursive_call + opimpl_recursive_call_r = _opimpl_recursive_call + opimpl_recursive_call_f = _opimpl_recursive_call + opimpl_recursive_call_v = _opimpl_recursive_call + +## @FixME #arguments("orgpc", "methdescr", "varargs") +## def opimpl_oosend(self, pc, methdescr, varargs): +## objbox = varargs[0] +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## oocls = clsbox.getref(ootype.Class) +## jitcode = methdescr.get_jitcode_for_class(oocls) +## if jitcode is not None: +## # we should follow calls to this graph +## return self.perform_call(jitcode, varargs) +## else: +## # but we should not follow calls to that graph +## return self.execute_varargs(rop.OOSEND, varargs, +## descr=methdescr, exc=True) @arguments("box") - def opimpl_strlen(self, str): - self.execute(rop.STRLEN, str) + def opimpl_strlen(self, strbox): + return self.execute(rop.STRLEN, strbox) @arguments("box") - def opimpl_unicodelen(self, str): - self.execute(rop.UNICODELEN, str) + def opimpl_unicodelen(self, unicodebox): + return self.execute(rop.UNICODELEN, unicodebox) @arguments("box", "box") - def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, str, index) + def opimpl_strgetitem(self, strbox, indexbox): + return self.execute(rop.STRGETITEM, strbox, indexbox) @arguments("box", "box") - def opimpl_unicodegetitem(self, str, index): - self.execute(rop.UNICODEGETITEM, str, index) + def opimpl_unicodegetitem(self, unicodebox, indexbox): + return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox) @arguments("box", "box", "box") - def opimpl_strsetitem(self, str, index, newchar): - self.execute(rop.STRSETITEM, str, index, newchar) + def opimpl_strsetitem(self, strbox, indexbox, newcharbox): + return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox) @arguments("box", "box", "box") - def opimpl_unicodesetitem(self, str, index, newchar): - self.execute(rop.UNICODESETITEM, str, index, newchar) + def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox): + self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox) @arguments("box") - def opimpl_newstr(self, length): - self.execute(rop.NEWSTR, length) + def opimpl_newstr(self, lengthbox): + return self.execute(rop.NEWSTR, lengthbox) @arguments("box") - def opimpl_newunicode(self, length): - self.execute(rop.NEWUNICODE, length) + def opimpl_newunicode(self, lengthbox): + return self.execute(rop.NEWUNICODE, lengthbox) - @arguments("descr", "varargs") - def opimpl_residual_oosend_canraise(self, methdescr, varargs): - return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_noraise(self, methdescr, varargs): - self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_pure(self, methdescr, boxes): - self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, exc=False) - - @arguments("orgpc", "box") - def opimpl_guard_value(self, pc, box): - constbox = self.implement_guard_value(pc, box) - self.make_result_box(constbox) - - @arguments("orgpc", "int") - def opimpl_guard_green(self, pc, boxindex): - """Like guard_value, but overwrites the original box with the const. - Used to prevent Boxes from showing up in the greenkey of some - operations, like jit_merge_point. The in-place overwriting is - convenient for jit_merge_point, which expects self.env to contain - not more than the greens+reds described in the jitdriver.""" - box = self.env[boxindex] - constbox = self.implement_guard_value(pc, box) - self.env[boxindex] = constbox +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_canraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=True) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_noraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=False) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_pure(self, methdescr, boxes): +## return self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, +## exc=False) + + @arguments("orgpc", "box",) + def _opimpl_guard_value(self, orgpc, box): + self.implement_guard_value(orgpc, box) + + opimpl_int_guard_value = _opimpl_guard_value + opimpl_ref_guard_value = _opimpl_guard_value + opimpl_float_guard_value = _opimpl_guard_value @arguments("orgpc", "box") - def opimpl_guard_class(self, pc, box): + def opimpl_guard_class(self, orgpc, box): clsbox = self.cls_of_box(box) - if isinstance(box, Box): - self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) - self.make_result_box(clsbox) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_builtin(self, pc, box, builtin): -## self.generate_guard(pc, "guard_builtin", box, [builtin]) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_len(self, pc, box, builtin): -## intbox = self.metainterp.cpu.execute_operation( -## 'len', [builtin.len_func, box], 'int') -## self.generate_guard(pc, "guard_len", box, [intbox]) - - @arguments("box") - def opimpl_keepalive(self, box): - pass # xxx? - - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args - for i in range(num_green_args): - assert isinstance(varargs[i], Const) - - def blackhole_reached_merge_point(self, varargs): - if self.metainterp.in_recursion: - portal_code = self.metainterp.staticdata.portal_code - # small hack: fish for the result box - lenenv = len(self.env) - raised = self.perform_call(portal_code, varargs) - # in general this cannot be assumed, but when blackholing, - # perform_call returns True only if an exception is called. In - # this case perform_call has called finishframe_exception - # already, so we need to return. - if raised: - return - if lenenv == len(self.env): - res = None - else: - assert lenenv == len(self.env) - 1 - res = self.env.pop() - self.metainterp.finishframe(res) - else: - raise self.metainterp.staticdata.ContinueRunningNormally(varargs) + self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + return clsbox @arguments() def opimpl_can_enter_jit(self): - # Note: when running with a BlackHole history, this 'can_enter_jit' - # may be completely skipped by the logic that replaces perform_call - # with rop.CALL. But in that case, no-one will check the flag anyway, - # so it's fine. if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - @arguments() - def opimpl_jit_merge_point(self): - if not self.metainterp.is_blackholing(): - self.verify_green_args(self.env) - # xxx we may disable the following line in some context later - self.debug_merge_point() - if self.metainterp.seen_can_enter_jit: - self.metainterp.seen_can_enter_jit = False - assert not self.metainterp.in_recursion - # ^^^ it's impossible to arrive here with in_recursion set - # to a non-zero value: seen_can_enter_jit can only be set - # to True by opimpl_can_enter_jit, which should be executed - # just before opimpl_jit_merge_point (no recursion inbetween). - try: - self.metainterp.reached_can_enter_jit(self.env) - except GiveUp: - self.metainterp.switch_to_blackhole(ABORT_BRIDGE) - if self.metainterp.is_blackholing(): - self.blackhole_reached_merge_point(self.env) - return True + def verify_green_args(self, varargs): + num_green_args = self.metainterp.staticdata.num_green_args + assert len(varargs) == num_green_args + for i in range(num_green_args): + assert isinstance(varargs[i], Const) + + @arguments("orgpc", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): + self.verify_green_args(greenboxes) + # xxx we may disable the following line in some context later + self.debug_merge_point(greenboxes) + if self.metainterp.seen_can_enter_jit: + self.metainterp.seen_can_enter_jit = False + # Assert that it's impossible to arrive here with in_recursion + # set to a non-zero value: seen_can_enter_jit can only be set + # to True by opimpl_can_enter_jit, which should be executed + # just before opimpl_jit_merge_point (no recursion inbetween). + assert not self.metainterp.in_recursion + # Set self.pc to point to jit_merge_point instead of just after: + # if reached_can_enter_jit() raises SwitchToBlackhole, then the + # pc is still at the jit_merge_point, which is a point that is + # much less expensive to blackhole out of. + saved_pc = self.pc + self.pc = orgpc + self.metainterp.reached_can_enter_jit(greenboxes, redboxes) + self.pc = saved_pc - def debug_merge_point(self): + def debug_merge_point(self, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - num_green_args = self.metainterp.staticdata.num_green_args - greenkey = self.env[:num_green_args] sd = self.metainterp.staticdata loc = sd.state.get_location_str(greenkey) debug_print(loc) @@ -871,45 +811,45 @@ self.metainterp.history.record(rop.DEBUG_MERGE_POINT, [constloc], None) - @arguments("jumptarget") - def opimpl_setup_exception_block(self, exception_target): - self.exception_target = exception_target - - @arguments() - def opimpl_teardown_exception_block(self): - self.exception_target = -1 - - @arguments("constbox", "jumptarget", "orgpc") - def opimpl_goto_if_exception_mismatch(self, vtableref, next_exc_target, pc): - # XXX used to be: - # assert isinstance(self.exception_box, Const) # XXX - # seems this can happen that self.exception_box is not a Const, - # but I failed to write a test so far :-( - self.exception_box = self.implement_guard_value(pc, self.exception_box) - cpu = self.metainterp.cpu - ts = self.metainterp.cpu.ts - if not ts.subclassOf(cpu, self.exception_box, vtableref): + @arguments("box", "label") + def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target): + metainterp = self.metainterp + last_exc_value_box = metainterp.last_exc_value_box + assert last_exc_value_box is not None + assert metainterp.class_of_last_exc_is_const + if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox): self.pc = next_exc_target - @arguments("int") - def opimpl_put_last_exception(self, index): - assert index >= 0 - self.env.insert(index, self.exception_box) - - @arguments("int") - def opimpl_put_last_exc_value(self, index): - assert index >= 0 - self.env.insert(index, self.exc_value_box) + @arguments("orgpc", "box") + def opimpl_raise(self, orgpc, exc_value_box): + # xxx hack + clsbox = self.cls_of_box(exc_value_box) + self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + resumepc=orgpc) + self.metainterp.class_of_last_exc_is_const = True + self.metainterp.last_exc_value_box = exc_value_box + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_raise(self): - assert len(self.env) == 2 - return self.metainterp.finishframe_exception(self.env[0], self.env[1]) + def opimpl_reraise(self): + assert self.metainterp.last_exc_value_box is not None + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_reraise(self): - return self.metainterp.finishframe_exception(self.exception_box, - self.exc_value_box) + def opimpl_last_exception(self): + # Same comment as in opimpl_goto_if_exception_mismatch(). + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + assert self.metainterp.class_of_last_exc_is_const + return self.metainterp.cpu.ts.cls_of_box(exc_value_box) + + @arguments() + def opimpl_last_exc_value(self): + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + return exc_value_box @arguments("box") def opimpl_virtual_ref(self, box): @@ -920,30 +860,26 @@ # the 'virtual_ref(frame)'). # # * if we detect that the virtual box escapes during tracing - # already (by generating a CALl_MAY_FORCE that marks the flags + # already (by generating a CALL_MAY_FORCE that marks the flags # in the vref), then we replace the vref in the list with # ConstPtr(NULL). # metainterp = self.metainterp - if metainterp.is_blackholing(): - resbox = box # good enough when blackholing - else: - vrefinfo = metainterp.staticdata.virtualref_info - obj = box.getref_base() - vref = vrefinfo.virtual_ref_during_tracing(obj) - resbox = history.BoxPtr(vref) - cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) - metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) - # Note: we allocate a JIT_VIRTUAL_REF here - # (in virtual_ref_during_tracing()), in order to detect when - # the virtual escapes during tracing already. We record it as a - # VIRTUAL_REF operation, although the backend sees this operation - # as a no-op. The point is that the backend should not really see - # it in practice, as optimizeopt.py should either kill it or - # replace it with a NEW_WITH_VTABLE followed by SETFIELD_GCs. + vrefinfo = metainterp.staticdata.virtualref_info + obj = box.getref_base() + vref = vrefinfo.virtual_ref_during_tracing(obj) + resbox = history.BoxPtr(vref) + cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) + metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) + # Note: we allocate a JIT_VIRTUAL_REF here + # (in virtual_ref_during_tracing()), in order to detect when + # the virtual escapes during tracing already. We record it as a + # VIRTUAL_REF operation. Later, optimizeopt.py should either kill + # that operation or replace it with a NEW_WITH_VTABLE followed by + # SETFIELD_GCs. metainterp.virtualref_boxes.append(box) metainterp.virtualref_boxes.append(resbox) - self.make_result_box(resbox) + return resbox @arguments("box") def opimpl_virtual_ref_finish(self, box): @@ -953,27 +889,32 @@ vrefbox = metainterp.virtualref_boxes.pop() lastbox = metainterp.virtualref_boxes.pop() assert box.getref_base() == lastbox.getref_base() - if not metainterp.is_blackholing(): - vrefinfo = metainterp.staticdata.virtualref_info - vref = vrefbox.getref_base() - if vrefinfo.is_virtual_ref(vref): - metainterp.history.record(rop.VIRTUAL_REF_FINISH, - [vrefbox, lastbox], None) + vrefinfo = metainterp.staticdata.virtualref_info + vref = vrefbox.getref_base() + if vrefinfo.is_virtual_ref(vref): + metainterp.history.record(rop.VIRTUAL_REF_FINISH, + [vrefbox, lastbox], None) # ------------------------------ def setup_call(self, argboxes): - if not we_are_translated(): - check_args(*argboxes) self.pc = 0 - self.env = argboxes + count_i = count_r = count_f = 0 + for box in argboxes: + if box.type == history.INT: + self.registers_i[count_i] = box + count_i += 1 + elif box.type == history.REF: + self.registers_r[count_r] = box + count_r += 1 + elif box.type == history.FLOAT: + self.registers_f[count_f] = box + count_f += 1 + else: + raise AssertionError(box.type) - def setup_resume_at_op(self, pc, exception_target, env): - if not we_are_translated(): - check_args(*env) + def setup_resume_at_op(self, pc): self.pc = pc - self.exception_target = exception_target - self.env = env ## values = ' '.join([box.repr_rpython() for box in self.env]) ## log('setup_resume_at_op %s:%d [%s] %d' % (self.jitcode.name, ## self.pc, values, @@ -984,25 +925,21 @@ # whenever the 'opcode_implementations' (which is one of the 'opimpl_' # methods) returns True. This is the case when the current frame # changes, due to a call or a return. - while True: - pc = self.pc - op = ord(self.bytecode[pc]) - #print self.jitcode.name, self.metainterp.staticdata.opcode_names[op] - self.pc = pc + 1 + try: staticdata = self.metainterp.staticdata - stop = staticdata.opcode_implementations[op](self, pc) - #self.metainterp.most_recent_mp = None - if stop: - break + while True: + pc = self.pc + op = ord(self.bytecode[pc]) + #debug_print(self.jitcode.name, pc) + #print staticdata.opcode_names[op] + staticdata.opcode_implementations[op](self, pc) + except ChangeFrame: + pass - def generate_guard(self, pc, opnum, box, extraargs=[]): + def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): if isinstance(box, Const): # no need for a guard return metainterp = self.metainterp - if metainterp.is_blackholing(): - return - saved_pc = self.pc - self.pc = pc if box is not None: moreargs = [box] + extraargs else: @@ -1020,15 +957,18 @@ virtualizable_boxes = None if metainterp.staticdata.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes + saved_pc = self.pc + if resumepc >= 0: + self.pc = resumepc resume.capture_resumedata(metainterp.framestack, virtualizable_boxes, metainterp.virtualref_boxes, resumedescr) + self.pc = saved_pc self.metainterp.staticdata.profiler.count_ops(opnum, GUARDS) # count metainterp.attach_debug_info(guard_op) - self.pc = saved_pc return guard_op - def implement_guard_value(self, pc, box): + def implement_guard_value(self, orgpc, box): """Promote the given Box into a Const. Note: be careful, it's a bit unclear what occurs if a single opcode needs to generate several ones and/or ones not near the beginning.""" @@ -1036,111 +976,190 @@ return box # no promotion needed, already a Const else: promoted_box = box.constbox() - self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box]) + self.generate_guard(rop.GUARD_VALUE, box, [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, promoted_box) return promoted_box def cls_of_box(self, box): - return self.metainterp.cpu.ts.cls_of_box(self.metainterp.cpu, box) + return self.metainterp.cpu.ts.cls_of_box(box) @specialize.arg(1) def execute(self, opnum, *argboxes): - self.execute_with_descr(opnum, None, *argboxes) + return self.metainterp.execute_and_record(opnum, None, *argboxes) @specialize.arg(1) def execute_with_descr(self, opnum, descr, *argboxes): - resbox = self.metainterp.execute_and_record(opnum, descr, *argboxes) - if resbox is not None: - self.make_result_box(resbox) + return self.metainterp.execute_and_record(opnum, descr, *argboxes) @specialize.arg(1) def execute_varargs(self, opnum, argboxes, descr, exc): + self.metainterp.clear_exception() resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes, descr=descr) - if resbox is not None: - self.make_result_box(resbox) + self.make_result_of_lastop(resbox) + # ^^^ this is done before handle_possible_exception() because we need + # the box to show up in get_list_of_active_boxes() if exc: - return self.metainterp.handle_exception() + self.metainterp.handle_possible_exception() else: - return self.metainterp.assert_no_exception() + self.metainterp.assert_no_exception() + return resbox - def do_residual_call(self, argboxes, descr, exc): + def do_residual_call(self, funcbox, descr, argboxes, + assembler_call_token=None): + # First build allboxes: it may need some reordering from the + # list provided in argboxes, depending on the order in which + # the arguments are expected by the function + allboxes = [None] * (len(argboxes)+1) + allboxes[0] = funcbox + src_i = src_r = src_f = 0 + i = 1 + for kind in descr.get_arg_types(): + if kind == history.INT: + while True: + box = argboxes[src_i] + src_i += 1 + if box.type == history.INT: + break + elif kind == history.REF: + while True: + box = argboxes[src_r] + src_r += 1 + if box.type == history.REF: + break + elif kind == history.FLOAT: + while True: + box = argboxes[src_f] + src_f += 1 + if box.type == history.FLOAT: + break + else: + raise AssertionError + allboxes[i] = box + i += 1 + assert i == len(allboxes) + # effectinfo = descr.get_extra_info() - if effectinfo is None or effectinfo.forces_virtual_or_virtualizable: + if (effectinfo is None or + effectinfo.extraeffect == + effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE or + assembler_call_token is not None): # residual calls require attention to keep virtualizables in-sync + self.metainterp.clear_exception() self.metainterp.vable_and_vrefs_before_residual_call() - # xxx do something about code duplication resbox = self.metainterp.execute_and_record_varargs( - rop.CALL_MAY_FORCE, argboxes, descr=descr) - self.metainterp.vable_and_vrefs_after_residual_call() + rop.CALL_MAY_FORCE, allboxes, descr=descr) + self.metainterp.vrefs_after_residual_call() + if assembler_call_token is not None: + self.metainterp.direct_assembler_call(assembler_call_token) if resbox is not None: - self.make_result_box(resbox) - self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, []) - if exc: - return self.metainterp.handle_exception() + self.make_result_of_lastop(resbox) + self.metainterp.vable_after_residual_call() + self.generate_guard(rop.GUARD_NOT_FORCED, None) + self.metainterp.handle_possible_exception() + return resbox + else: + effect = effectinfo.extraeffect + if effect == effectinfo.EF_CANNOT_RAISE: + return self.execute_varargs(rop.CALL, allboxes, descr, False) + elif effect == effectinfo.EF_PURE: + return self.metainterp.record_result_of_call_pure( + self.execute_varargs(rop.CALL, allboxes, descr, False)) + elif effect == effectinfo.EF_LOOPINVARIANT: + return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes, + descr, True) else: - return self.metainterp.assert_no_exception() + return self.execute_varargs(rop.CALL, allboxes, descr, True) + + def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes): + """The 'residual_call' operation is emitted in two cases: + when we have to generate a residual CALL operation, but also + to handle an indirect_call that may need to be inlined.""" + assert isinstance(funcbox, Const) + sd = self.metainterp.staticdata + key = sd.cpu.ts.getaddr_for_box(funcbox) + jitcode = sd.bytecode_for_address(key) + if jitcode is not None: + # we should follow calls to this graph + return self.metainterp.perform_call(jitcode, argboxes) else: - return self.execute_varargs(rop.CALL, argboxes, descr, exc) + # but we should not follow calls to that graph + return self.do_residual_call(funcbox, calldescr, argboxes) # ____________________________________________________________ class MetaInterpStaticData(object): - virtualizable_info = None logger_noopt = None logger_ops = None - def __init__(self, portal_graph, cpu, stats, options, + def __init__(self, cpu, options, ProfilerClass=EmptyProfiler, warmrunnerdesc=None): self.cpu = cpu - self.stats = stats + self.stats = self.cpu.stats self.options = options self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) - RESULT = portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) - - self.opcode_implementations = [] - self.opcode_names = [] - self.opname_to_index = {} - self.profiler = ProfilerClass() - - self.indirectcall_keys = [] - self.indirectcall_values = [] - self.warmrunnerdesc = warmrunnerdesc - self._op_goto_if_not = self.find_opcode('goto_if_not') - self._op_ooisnull = self.find_opcode('ooisnull') - self._op_oononnull = self.find_opcode('oononnull') backendmodule = self.cpu.__module__ backendmodule = backendmodule.split('.')[-2] self.jit_starting_line = 'JIT starting (%s)' % backendmodule - self.portal_code = None - self._class_sizes = None self._addr2name_keys = [] self._addr2name_values = [] self.__dict__.update(compile.make_done_loop_tokens()) - # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) def _freeze_(self): return True - def info_from_codewriter(self, portal_code, class_sizes, - list_of_addr2name, portal_runner_ptr): - self.portal_code = portal_code - self._class_sizes = class_sizes - self._addr2name_keys = [key for key, value in list_of_addr2name] + def setup_insns(self, insns): + self.opcode_names = ['?'] * len(insns) + self.opcode_implementations = [None] * len(insns) + for key, value in insns.items(): + assert self.opcode_implementations[value] is None + self.opcode_names[value] = key + name, argcodes = key.split('/') + opimpl = _get_opimpl_method(name, argcodes) + self.opcode_implementations[value] = opimpl + self.op_catch_exception = insns.get('catch_exception/L', -1) + + def setup_descrs(self, descrs): + self.opcode_descrs = descrs + + def setup_indirectcalltargets(self, indirectcalltargets): + self.indirectcalltargets = list(indirectcalltargets) + + def setup_list_of_addr2name(self, list_of_addr2name): + self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] - self._portal_runner_ptr = portal_runner_ptr - def finish_setup(self, optimizer=None): + def finish_setup(self, codewriter, optimizer=None): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) + # + asm = codewriter.assembler + self.setup_insns(asm.insns) + self.setup_descrs(asm.descrs) + self.setup_indirectcalltargets(asm.indirectcalltargets) + self.setup_list_of_addr2name(asm.list_of_addr2name) + # + self.portal_code = codewriter.mainjitcode + self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.virtualref_info = codewriter.callcontrol.virtualref_info + self.virtualizable_info = codewriter.callcontrol.virtualizable_info + RESULT = codewriter.portal_graph.getreturnvar().concretetype + self.result_type = history.getkind(RESULT) + # + # store this information for fastpath of call_assembler + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args @@ -1156,20 +1175,12 @@ """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: debug_print(self.jit_starting_line) - self._setup_class_sizes() self.cpu.setup_once() if not self.profiler.initialized: self.profiler.start() self.profiler.initialized = True self.globaldata.initialized = True - def _setup_class_sizes(self): - class_sizes = {} - for vtable, sizedescr in self._class_sizes: - vtable = self.cpu.ts.cast_vtable_to_hashable(self.cpu, vtable) - class_sizes[vtable] = sizedescr - self.cpu.set_class_sizes(class_sizes) - def get_name_from_address(self, addr): # for debugging only if we_are_translated(): @@ -1200,39 +1211,16 @@ # because the keys are function addresses, so they # can change from run to run. d = {} - keys = self.indirectcall_keys - values = self.indirectcall_values - for i in range(len(keys)): - d[keys[i]] = values[i] + for jitcode in self.indirectcalltargets: + d[jitcode.fnaddr] = jitcode self.globaldata.indirectcall_dict = d return d.get(fnaddress, None) else: - for i in range(len(self.indirectcall_keys)): - if fnaddress == self.indirectcall_keys[i]: - return self.indirectcall_values[i] + for jitcode in self.indirectcalltargets: + if jitcode.fnaddr == fnaddress: + return jitcode return None - # ---------- construction-time interface ---------- - - def _register_indirect_call_target(self, fnaddress, jitcode): - self.indirectcall_keys.append(fnaddress) - self.indirectcall_values.append(jitcode) - - def find_opcode(self, name): - try: - return self.opname_to_index[name] - except KeyError: - self._register_opcode(name) - return self.opname_to_index[name] - - def _register_opcode(self, opname): - assert len(self.opcode_implementations) < 256, \ - "too many implementations of opcodes!" - name = "opimpl_" + opname - self.opname_to_index[opname] = len(self.opcode_implementations) - self.opcode_names.append(opname) - self.opcode_implementations.append(getattr(MIFrame, name).im_func) - # ---------------- logging ------------------------ def log(self, msg): @@ -1259,6 +1247,7 @@ self.addr2name = None self.loopnumbering = 0 self.resume_virtuals = {} + self.resume_virtuals_not_translated = [] # state = staticdata.state if state is not None: @@ -1283,23 +1272,32 @@ class MetaInterp(object): in_recursion = 0 - _already_allocated_resume_virtuals = None def __init__(self, staticdata): self.staticdata = staticdata self.cpu = staticdata.cpu self.portal_trace_positions = [] + self.free_frames_list = [] + self.last_exc_value_box = None - def is_blackholing(self): - return self.history is None + def perform_call(self, jitcode, boxes, greenkey=None): + # causes the metainterp to enter the given subfunction + # with a special case for recursive portal calls + f = self.newframe(jitcode, greenkey) + f.setup_call(boxes) + raise ChangeFrame def newframe(self, jitcode, greenkey=None): if jitcode is self.staticdata.portal_code: self.in_recursion += 1 - if greenkey is not None and not self.is_blackholing(): + if greenkey is not None: self.portal_trace_positions.append( (greenkey, len(self.history.operations))) - f = MIFrame(self, jitcode, greenkey) + if len(self.free_frames_list) > 0: + f = self.free_frames_list.pop() + else: + f = MIFrame(self) + f.setup(jitcode, greenkey) self.framestack.append(f) return f @@ -1307,23 +1305,27 @@ frame = self.framestack.pop() if frame.jitcode is self.staticdata.portal_code: self.in_recursion -= 1 - if frame.greenkey is not None and not self.is_blackholing(): + if frame.greenkey is not None: self.portal_trace_positions.append( (None, len(self.history.operations))) - return frame + # we save the freed MIFrames to avoid needing to re-create new + # MIFrame objects all the time; they are a bit big, with their + # 3*256 register entries. + frame.cleanup_registers() + self.free_frames_list.append(frame) def finishframe(self, resultbox): - frame = self.popframe() + # handle a non-exceptional return from the current frame + self.last_exc_value_box = None + self.popframe() if self.framestack: - if resultbox is not None: - self.framestack[-1].make_result_box(resultbox) - return True + self.framestack[-1].make_result_of_lastop(resultbox) + raise ChangeFrame else: - if not self.is_blackholing(): - try: - self.compile_done_with_this_frame(resultbox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_done_with_this_frame(resultbox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) sd = self.staticdata if sd.result_type == 'void': assert resultbox is None @@ -1337,30 +1339,25 @@ else: assert False - def finishframe_exception(self, exceptionbox, excvaluebox): - # detect and propagate some exceptions early: - # - AssertionError - # - all subclasses of JitException - if we_are_translated(): - from pypy.jit.metainterp.warmspot import JitException - e = self.cpu.ts.get_exception_obj(excvaluebox) - if isinstance(e, JitException) or isinstance(e, AssertionError): - raise Exception, e - # + def finishframe_exception(self): + excvaluebox = self.last_exc_value_box while self.framestack: frame = self.framestack[-1] - if frame.exception_target >= 0: - frame.pc = frame.exception_target - frame.exception_target = -1 - frame.exception_box = exceptionbox - frame.exc_value_box = excvaluebox - return True + code = frame.bytecode + position = frame.pc # <-- just after the insn that raised + if position < len(code): + opcode = ord(code[position]) + if opcode == self.staticdata.op_catch_exception: + # found a 'catch_exception' instruction; + # jump to the handler + target = ord(code[position+1]) | (ord(code[position+2])<<8) + frame.pc = target + raise ChangeFrame self.popframe() - if not self.is_blackholing(): - try: - self.compile_exit_frame_with_exception(excvaluebox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_exit_frame_with_exception(excvaluebox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base()) def check_recursion_invariant(self): @@ -1379,19 +1376,7 @@ else: print " ", print jitcode.name - raise Exception - - def raise_overflow_error(self): - etype, evalue = self.cpu.get_overflow_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) - - def raise_zero_division_error(self): - etype, evalue = self.cpu.get_zero_division_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) + raise AssertionError def create_empty_history(self): warmrunnerstate = self.staticdata.state @@ -1412,15 +1397,11 @@ @specialize.arg(1) def execute_and_record(self, opnum, descr, *argboxes): history.check_descr(descr) - assert (opnum != rop.CALL and opnum != rop.CALL_MAY_FORCE - and opnum != rop.OOSEND) + assert not (rop._CANRAISE_FIRST <= opnum <= rop._CANRAISE_LAST) # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - return resbox + resbox = executor.execute(self.cpu, self, opnum, descr, *argboxes) if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: return self._record_helper_pure(opnum, resbox, descr, *argboxes) else: @@ -1433,16 +1414,14 @@ # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute_varargs(self.cpu, opnum, argboxes, descr) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - else: - # check if the operation can be constant-folded away - argboxes = list(argboxes) - if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: - resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) - else: - resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) + resbox = executor.execute_varargs(self.cpu, self, + opnum, argboxes, descr) + # check if the operation can be constant-folded away + argboxes = list(argboxes) + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: + resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) + else: + resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) return resbox def _record_helper_pure(self, opnum, resbox, descr, *argboxes): @@ -1478,45 +1457,57 @@ op.pc = self.framestack[-1].pc op.name = self.framestack[-1].jitcode.name - def switch_to_blackhole(self, reason): + def execute_raised(self, exception, constant=False): + if isinstance(exception, JitException): + raise JitException, exception # go through + llexception = get_llexception(self.cpu, exception) + self.execute_ll_raised(llexception, constant) + + def execute_ll_raised(self, llexception, constant=False): + # Exception handling: when execute.do_call() gets an exception it + # calls metainterp.execute_raised(), which puts it into + # 'self.last_exc_value_box'. This is used shortly afterwards + # to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also + # to handle the following opcodes 'goto_if_exception_mismatch'. + llexception = self.cpu.ts.cast_to_ref(llexception) + exc_value_box = self.cpu.ts.get_exc_value_box(llexception) + if constant: + exc_value_box = exc_value_box.constbox() + self.last_exc_value_box = exc_value_box + self.class_of_last_exc_is_const = constant + # 'class_of_last_exc_is_const' means that the class of the value + # stored in the exc_value Box can be assumed to be a Const. This + # is only True after a GUARD_EXCEPTION or GUARD_CLASS. + + def clear_exception(self): + self.last_exc_value_box = None + + def aborted_tracing(self, reason): self.staticdata.profiler.count(reason) debug_print('~~~ ABORTING TRACING') - debug_stop('jit-tracing') - debug_start('jit-blackhole') - self.history = None # start blackholing self.staticdata.stats.aborted() - self.staticdata.profiler.end_tracing() - self.staticdata.profiler.start_blackhole() self.resumekey.reset_counter_from_failure() - switch_to_blackhole._dont_inline_ = True - def switch_to_blackhole_if_trace_too_long(self): - if not self.is_blackholing(): - warmrunnerstate = self.staticdata.state - if len(self.history.operations) > warmrunnerstate.trace_limit: - greenkey_of_huge_function = self.find_biggest_function() - self.portal_trace_positions = None - self.switch_to_blackhole(ABORT_TOO_LONG) - if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state - warmrunnerstate.disable_noninlinable_function( - greenkey_of_huge_function) + def blackhole_if_trace_too_long(self): + warmrunnerstate = self.staticdata.state + if len(self.history.operations) > warmrunnerstate.trace_limit: + greenkey_of_huge_function = self.find_biggest_function() + self.portal_trace_positions = None + if greenkey_of_huge_function is not None: + warmrunnerstate = self.staticdata.state + warmrunnerstate.disable_noninlinable_function( + greenkey_of_huge_function) + raise SwitchToBlackhole(ABORT_TOO_LONG) def _interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, - # a ContinueRunningNormally, or a GenerateMergePoint exception. + # a ExitFrameWithException, or a GenerateMergePoint exception. self.staticdata.stats.entered() - try: - while True: - self.framestack[-1].run_one_step() - self.switch_to_blackhole_if_trace_too_long() - if not we_are_translated(): - self.check_recursion_invariant() - finally: - if self.is_blackholing(): - self.staticdata.profiler.end_blackhole() - else: - self.staticdata.profiler.end_tracing() + while True: + self.framestack[-1].run_one_step() + self.blackhole_if_trace_too_long() + if not we_are_translated(): + self.check_recursion_invariant() def interpret(self): if we_are_translated(): @@ -1527,20 +1518,19 @@ except: import sys if sys.exc_info()[0] is not None: - codewriter.log.info(sys.exc_info()[0].__name__) + self.staticdata.log(sys.exc_info()[0].__name__) raise def compile_and_run_once(self, *args): debug_start('jit-tracing') self.staticdata._setup_once() + self.staticdata.profiler.start_tracing() self.create_empty_history() try: return self._compile_and_run_once(*args) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _compile_and_run_once(self, *args): original_boxes = self.initialize_state_from_start(*args) @@ -1553,20 +1543,22 @@ self.seen_can_enter_jit = False try: self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" def handle_guard_failure(self, key): + debug_start('jit-tracing') + self.staticdata.profiler.start_tracing() assert isinstance(key, compile.ResumeGuardDescr) self.initialize_state_from_guard_failure(key) try: return self._handle_guard_failure(key) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _handle_guard_failure(self, key): original_greenkey = key.original_greenkey @@ -1579,13 +1571,23 @@ try: self.prepare_resume_from_failure(key.guard_opnum) self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" + + def run_blackhole_interp_to_cancel_tracing(self, stb): + # We got a SwitchToBlackhole exception. Convert the framestack into + # a stack of blackhole interpreters filled with the same values, and + # run it. + from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl + self.aborted_tracing(stb.reason) + convert_and_run_from_pyjitpl(self, stb.raising_exception) + assert False # ^^^ must raise - def remove_consts_and_duplicates(self, boxes, startindex, endindex, - duplicates): - for i in range(startindex, endindex): + def remove_consts_and_duplicates(self, boxes, endindex, duplicates): + for i in range(endindex): box = boxes[i] if isinstance(box, Const) or box in duplicates: oldbox = box @@ -1595,22 +1597,19 @@ else: duplicates[box] = None - def reached_can_enter_jit(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + def reached_can_enter_jit(self, greenboxes, redboxes): duplicates = {} - self.remove_consts_and_duplicates(live_arg_boxes, - num_green_args, - len(live_arg_boxes), + self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) - live_arg_boxes = live_arg_boxes[:] + live_arg_boxes = greenboxes + redboxes if self.staticdata.virtualizable_info is not None: - # we use ':-1' to remove the last item, which is the virtualizable + # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, - 0, len(self.virtualizable_boxes)-1, duplicates) - live_arg_boxes += self.virtualizable_boxes[:-1] + live_arg_boxes += self.virtualizable_boxes + live_arg_boxes.pop() assert len(self.virtualref_boxes) == 0, "missing virtual_ref_finish()?" # Called whenever we reach the 'can_enter_jit' hint. # First, attempt to make a bridge: @@ -1639,11 +1638,12 @@ # Found! Compile it as a loop. if start < 0: # we cannot reconstruct the beginning of the proper loop - raise GiveUp + raise SwitchToBlackhole(ABORT_BRIDGE) # raises in case it works -- which is the common case self.compile(original_boxes, live_arg_boxes, start) # creation of the loop was cancelled! + self.staticdata.log('cancelled, going on...') # Otherwise, no loop found so far, so continue tracing. start = len(self.history.operations) @@ -1658,17 +1658,39 @@ return loop_token def prepare_resume_from_failure(self, opnum): + frame = self.framestack[-1] if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now - self.framestack[-1].follow_jump() + frame.pc = frame.jitcode.follow_jump(frame.pc) elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping - self.framestack[-1].dont_follow_jump() - elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION - or opnum == rop.GUARD_NOT_FORCED): - self.handle_exception() + pass + elif opnum == rop.GUARD_VALUE or opnum == rop.GUARD_CLASS: + pass # the pc is already set to the *start* of the opcode + elif (opnum == rop.GUARD_NONNULL or + opnum == rop.GUARD_ISNULL or + opnum == rop.GUARD_NONNULL_CLASS): + pass # the pc is already set to the *start* of the opcode + elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION: + exception = self.cpu.grab_exc_value() + if exception: + self.execute_ll_raised(lltype.cast_opaque_ptr(rclass.OBJECTPTR, + exception)) + else: + self.clear_exception() + try: + self.handle_possible_exception() + except ChangeFrame: + pass elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected - self.raise_overflow_error() - elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL: - self.framestack[-1].ignore_next_guard_nullness(opnum) + self.execute_raised(OverflowError(), constant=True) + try: + self.finishframe_exception() + except ChangeFrame: + pass + elif opnum == rop.GUARD_OVERFLOW: # no longer overflowing + self.clear_exception() + else: + from pypy.jit.metainterp.resoperation import opname + raise NotImplementedError(opname[opnum]) def compile(self, original_boxes, live_arg_boxes, start): num_green_args = self.staticdata.num_green_args @@ -1719,7 +1741,8 @@ self.history.record(rop.JUMP, exits, None) target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + compile.giveup() def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1729,7 +1752,8 @@ loop_tokens = sd.loop_tokens_exit_frame_with_exception_ref target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) - assert target_loop_token is loop_tokens[0] + if target_loop_token is not loop_tokens[0]: + compile.giveup() def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests @@ -1751,15 +1775,13 @@ def initialize_state_from_start(self, *args): self.in_recursion = -1 # always one portal around - self.staticdata.profiler.start_tracing() num_green_args = self.staticdata.num_green_args original_boxes = [] self._initialize_from_start(original_boxes, num_green_args, *args) # ----- make a new frame ----- self.framestack = [] f = self.newframe(self.staticdata.portal_code) - f.pc = 0 - f.env = original_boxes[:] + f.setup_call(original_boxes) self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) return original_boxes @@ -1767,20 +1789,9 @@ def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack self.in_recursion = -1 # always one portal around - inputargs_and_holes = self.cpu.make_boxes_from_latest_values( - resumedescr) - must_compile = resumedescr.must_compile(self.staticdata, - inputargs_and_holes) - if must_compile: - debug_start('jit-tracing') - self.history = history.History() - self.history.inputargs = [box for box in inputargs_and_holes if box] - self.staticdata.profiler.start_tracing() - else: - debug_start('jit-blackhole') - self.staticdata.profiler.start_blackhole() - self.history = None # this means that is_blackholing() is true - self.rebuild_state_after_failure(resumedescr, inputargs_and_holes) + self.history = history.History() + inputargs_and_holes = self.rebuild_state_after_failure(resumedescr) + self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): vinfo = self.staticdata.virtualizable_info @@ -1802,9 +1813,6 @@ vinfo.clear_vable_token(virtualizable) def vable_and_vrefs_before_residual_call(self): - if self.is_blackholing(): - return - # vrefinfo = self.staticdata.virtualref_info for i in range(1, len(self.virtualref_boxes), 2): vrefbox = self.virtualref_boxes[i] @@ -1825,37 +1833,31 @@ force_token_box], None, descr=vinfo.vable_token_descr) - def vable_and_vrefs_after_residual_call(self): - if self.is_blackholing(): - escapes = True - else: - escapes = False - # - vrefinfo = self.staticdata.virtualref_info - for i in range(0, len(self.virtualref_boxes), 2): - virtualbox = self.virtualref_boxes[i] - vrefbox = self.virtualref_boxes[i+1] - vref = vrefbox.getref_base() - if vrefinfo.tracing_after_residual_call(vref): - # this vref was really a virtual_ref, but it escaped - # during this CALL_MAY_FORCE. Mark this fact by - # generating a VIRTUAL_REF_FINISH on it and replacing - # it by ConstPtr(NULL). - self.stop_tracking_virtualref(i) - # - vinfo = self.staticdata.virtualizable_info - if vinfo is not None: - virtualizable_box = self.virtualizable_boxes[-1] - virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) - if vinfo.tracing_after_residual_call(virtualizable): - # the virtualizable escaped during CALL_MAY_FORCE. - escapes = True - # - if escapes: - self.switch_to_blackhole(ABORT_ESCAPE) - # - if escapes: - self.load_fields_from_virtualizable() + def vrefs_after_residual_call(self): + vrefinfo = self.staticdata.virtualref_info + for i in range(0, len(self.virtualref_boxes), 2): + virtualbox = self.virtualref_boxes[i] + vrefbox = self.virtualref_boxes[i+1] + vref = vrefbox.getref_base() + if vrefinfo.tracing_after_residual_call(vref): + # this vref was really a virtual_ref, but it escaped + # during this CALL_MAY_FORCE. Mark this fact by + # generating a VIRTUAL_REF_FINISH on it and replacing + # it by ConstPtr(NULL). + self.stop_tracking_virtualref(i) + + def vable_after_residual_call(self): + vinfo = self.staticdata.virtualizable_info + if vinfo is not None: + virtualizable_box = self.virtualizable_boxes[-1] + virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + if vinfo.tracing_after_residual_call(virtualizable): + # the virtualizable escaped during CALL_MAY_FORCE. + self.load_fields_from_virtualizable() + raise SwitchToBlackhole(ABORT_ESCAPE, raising_exception=True) + # ^^^ we set 'raising_exception' to True because we must still + # have the eventual exception raised (this is normally done + # after the call to vable_after_residual_call()). def stop_tracking_virtualref(self, i): virtualbox = self.virtualref_boxes[i] @@ -1869,44 +1871,37 @@ # mark by replacing it with ConstPtr(NULL) self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL - def handle_exception(self): - etype = self.cpu.get_exception() - evalue = self.cpu.get_exc_value() - assert bool(etype) == bool(evalue) - self.cpu.clear_exception() + def handle_possible_exception(self): frame = self.framestack[-1] - if etype: - exception_box = self.cpu.ts.get_exception_box(etype) - exc_value_box = self.cpu.ts.get_exc_value_box(evalue) - op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION, + if self.last_exc_value_box is not None: + exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box) + op = frame.generate_guard(rop.GUARD_EXCEPTION, None, [exception_box]) - if op: - op.result = exc_value_box - return self.finishframe_exception(exception_box, exc_value_box) + assert op is not None + op.result = self.last_exc_value_box + self.class_of_last_exc_is_const = True + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) - return False - - def assert_no_exception(self): - assert not self.cpu.get_exception() - return False + frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) - def handle_overflow_error(self): + def handle_possible_overflow_error(self): frame = self.framestack[-1] - if self.cpu._overflow_flag: - self.cpu._overflow_flag = False - frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None, []) - return self.raise_overflow_error() + if self.last_exc_value_box is not None: + frame.generate_guard(rop.GUARD_OVERFLOW, None) + assert isinstance(self.last_exc_value_box, Const) + assert self.class_of_last_exc_is_const + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None, []) - return False + frame.generate_guard(rop.GUARD_NO_OVERFLOW, None) + + def assert_no_exception(self): + assert self.last_exc_value_box is None - def rebuild_state_after_failure(self, resumedescr, newboxes): + def rebuild_state_after_failure(self, resumedescr): vinfo = self.staticdata.virtualizable_info self.framestack = [] - expect_virtualizable = vinfo is not None - virtualizable_boxes, virtualref_boxes = resume.rebuild_from_resumedata( - self, newboxes, resumedescr, expect_virtualizable) + boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) + inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists # # virtual refs: make the vrefs point to the freshly allocated virtuals self.virtualref_boxes = virtualref_boxes @@ -1919,7 +1914,7 @@ # # virtualizable: synchronize the real virtualizable and the local # boxes, in whichever direction is appropriate - if expect_virtualizable: + if vinfo is not None: self.virtualizable_boxes = virtualizable_boxes # just jumped away from assembler (case 4 in the comment in # virtualizable.py) into tracing (case 2); check that vable_token @@ -1928,13 +1923,14 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if self._already_allocated_resume_virtuals is not None: + if 0: ## self._already_allocated_resume_virtuals is not None: # resuming from a ResumeGuardForcedDescr: load the new values # currently stored on the virtualizable fields self.load_fields_from_virtualizable() else: # normal case: fill the virtualizable with the local boxes self.synchronize_virtualizable() + return inputargs_and_holes def check_synchronized_virtualizable(self): if not we_are_translated(): @@ -1951,8 +1947,8 @@ def load_fields_from_virtualizable(self): # Force a reload of the virtualizable fields into the local - # boxes (called only in escaping cases) - assert self.is_blackholing() + # boxes (called only in escaping cases). Only call this function + # just before SwitchToBlackhole. vinfo = self.staticdata.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] @@ -2001,11 +1997,9 @@ return boxes def replace_box(self, oldbox, newbox): + assert isinstance(oldbox, Box) for frame in self.framestack: - boxes = frame.env - for i in range(len(boxes)): - if boxes[i] is oldbox: - boxes[i] = newbox + frame.replace_active_box_in_frame(oldbox, newbox) boxes = self.virtualref_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2017,8 +2011,6 @@ boxes[i] = newbox def find_biggest_function(self): - assert not self.is_blackholing() - start_stack = [] max_size = 0 max_key = None @@ -2040,23 +2032,178 @@ max_key = key return max_key - def direct_assembler_call(self, pc, varargs, token, call_position): - """ Generate a direct call to assembler for portal entry point. + def record_result_of_call_pure(self, resbox): + """ Patch a CALL into a CALL_PURE. + """ + op = self.history.operations[-1] + assert op.opnum == rop.CALL + resbox_as_const = resbox.constbox() + for arg in op.args: + if not isinstance(arg, Const): + break + else: + # all-constants: remove the CALL operation now and propagate a + # constant result + self.history.operations.pop() + return resbox_as_const + # not all constants (so far): turn CALL into CALL_PURE, which might + # be either removed later by optimizeopt or turned back into CALL. + op.opnum = rop.CALL_PURE + op.args = [resbox_as_const] + op.args + return resbox + + def direct_assembler_call(self, token): + """ Generate a direct call to assembler for portal entry point, + patching the CALL_MAY_FORCE that occurred just now. """ - assert not self.is_blackholing() # XXX + op = self.history.operations.pop() + assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args - args = varargs[num_green_args + 1:] - resbox = self.history.operations[call_position].result - rest = self.history.slice_history_at(call_position) + args = op.args[num_green_args + 1:] if self.staticdata.virtualizable_info is not None: vindex = self.staticdata.virtualizable_info.index_of_virtualizable vbox = args[vindex - num_green_args] - args += self.gen_load_from_other_virtualizable(vbox) - self.history.record(rop.CALL_ASSEMBLER, args[:], resbox, descr=token) - self.history.operations += rest + args = args + self.gen_load_from_other_virtualizable(vbox) + # ^^^ and not "+=", which makes 'args' a resizable list + op.opnum = rop.CALL_ASSEMBLER + op.args = args + op.descr = token + self.history.operations.append(op) -class GenerateMergePoint(Exception): +# ____________________________________________________________ + +class GenerateMergePoint(JitException): def __init__(self, args, target_loop_token): assert target_loop_token is not None self.argboxes = args self.target_loop_token = target_loop_token + +class ChangeFrame(JitException): + """Raised after we mutated metainterp.framestack, in order to force + it to reload the current top-of-stack frame that gets interpreted.""" + +class SwitchToBlackhole(JitException): + def __init__(self, reason, raising_exception=False): + self.reason = reason + self.raising_exception = raising_exception + # ^^^ must be set to True if the SwitchToBlackhole is raised at a + # point where the exception on metainterp.last_exc_value_box + # is supposed to be raised. The default False means that it + # should just be copied into the blackhole interp, but not raised. + +# ____________________________________________________________ + +def _get_opimpl_method(name, argcodes): + from pypy.jit.metainterp.blackhole import signedord + # + def handler(self, position): + assert position >= 0 + args = () + next_argcode = 0 + code = self.bytecode + orgpc = position + position += 1 + for argtype in argtypes: + if argtype == "box": # a box, of whatever type + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = self.registers_i[ord(code[position])] + elif argcode == 'c': + value = ConstInt(signedord(code[position])) + elif argcode == 'r': + value = self.registers_r[ord(code[position])] + elif argcode == 'f': + value = self.registers_f[ord(code[position])] + else: + raise AssertionError("bad argcode") + position += 1 + elif argtype == "descr" or argtype == "jitcode": + assert argcodes[next_argcode] == 'd' + next_argcode = next_argcode + 1 + index = ord(code[position]) | (ord(code[position+1])<<8) + value = self.metainterp.staticdata.opcode_descrs[index] + if argtype == "jitcode": + assert isinstance(value, JitCode) + position += 2 + elif argtype == "label": + assert argcodes[next_argcode] == 'L' + next_argcode = next_argcode + 1 + value = ord(code[position]) | (ord(code[position+1])<<8) + position += 2 + elif argtype == "boxes": # a list of boxes of some type + length = ord(code[position]) + value = [None] * length + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + next_argcode = next_argcode + 1 + position += 1 + length + elif argtype == "boxes2": # two lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + value = [None] * (length1 + length2) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + next_argcode = next_argcode + 2 + position = position2 + 1 + length2 + elif argtype == "boxes3": # three lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + position3 = position2 + 1 + length2 + length3 = ord(code[position3]) + value = [None] * (length1 + length2 + length3) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + self.prepare_list_of_boxes(value, length1 + length2, position3, + argcodes[next_argcode + 2]) + next_argcode = next_argcode + 3 + position = position3 + 1 + length3 + elif argtype == "orgpc": + value = orgpc + else: + raise AssertionError("bad argtype: %r" % (argtype,)) + args += (value,) + # + num_return_args = len(argcodes) - next_argcode + assert num_return_args == 0 or num_return_args == 2 + if num_return_args: + # Save the type of the resulting box. This is needed if there is + # a get_list_of_active_boxes(). See comments there. + self._result_argcode = argcodes[next_argcode + 1] + position += 1 + else: + self._result_argcode = 'v' + self.pc = position + # + if not we_are_translated(): + print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))), + try: + resultbox = unboundmethod(self, *args) + except Exception, e: + print '-> %s!' % e.__class__.__name__ + raise + if num_return_args == 0: + print + assert resultbox is None + else: + print '-> %r' % (resultbox,) + assert argcodes[next_argcode] == '>' + result_argcode = argcodes[next_argcode + 1] + assert resultbox.type == {'i': history.INT, + 'r': history.REF, + 'f': history.FLOAT}[result_argcode] + else: + resultbox = unboundmethod(self, *args) + # + self.make_result_of_lastop(resultbox) + # + unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func + argtypes = unrolling_iterable(unboundmethod.argtypes) + handler.func_name = 'handler_' + name + return handler Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resoperation.py Fri Jun 18 20:55:39 2010 @@ -22,10 +22,11 @@ self.setdescr(descr) def setdescr(self, descr): - # for 'call', 'new', 'getfield_gc'...: the descr is a number provided - # by the backend holding details about the type of the operation -- - # actually an instance of a class, typically Descr, that inherits - # from AbstractDescr + # for 'call', 'new', 'getfield_gc'...: the descr is a prebuilt + # instance provided by the backend holding details about the type + # of the operation. It must inherit from AbstractDescr. The + # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(), + # cpu.calldescrof(), and cpu.typedescrof(). from pypy.jit.metainterp.history import check_descr check_descr(descr) self.descr = descr @@ -134,10 +135,6 @@ '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations ----- '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations ----- - 'OOSEND_PURE', # ootype operation - 'CALL_PURE', - # - 'CAST_PTR_TO_INT/1', 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', @@ -156,7 +153,6 @@ 'FLOAT_TRUEDIV/2', 'FLOAT_NEG/1', 'FLOAT_ABS/1', - 'FLOAT_IS_TRUE/1b', 'CAST_FLOAT_TO_INT/1', 'CAST_INT_TO_FLOAT/1', # @@ -177,15 +173,15 @@ 'FLOAT_GT/2b', 'FLOAT_GE/2b', # + 'INT_IS_ZERO/1b', 'INT_IS_TRUE/1b', 'INT_NEG/1', 'INT_INVERT/1', - 'BOOL_NOT/1b', # 'SAME_AS/1', # gets a Const or a Box, turns it into another Box # - 'OOIS/2b', - 'OOISNOT/2b', + 'PTR_EQ/2b', + 'PTR_NE/2b', # 'ARRAYLEN_GC/1d', 'STRLEN/1', @@ -197,8 +193,8 @@ 'UNICODEGETITEM/2', # # ootype operations - 'INSTANCEOF/1db', - 'SUBCLASSOF/2b', + #'INSTANCEOF/1db', + #'SUBCLASSOF/2b', # '_ALWAYS_PURE_LAST', # ----- end of always_pure operations ----- @@ -209,29 +205,32 @@ 'NEW_WITH_VTABLE/1', 'NEW_ARRAY/1d', 'FORCE_TOKEN/0', - 'VIRTUAL_REF/2', + 'VIRTUAL_REF/2', # removed before it's passed to the backend '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations ----- 'SETARRAYITEM_GC/3d', 'SETARRAYITEM_RAW/3d',#only added by backend.llsupport.gc.rewrite_assembler 'SETFIELD_GC/2d', 'SETFIELD_RAW/2d', - 'ARRAYCOPY/7d', + 'ARRAYCOPY/7d', # removed before it's passed to the backend 'NEWSTR/1', 'STRSETITEM/3', 'UNICODESETITEM/3', 'NEWUNICODE/1', - 'RUNTIMENEW/1', # ootype operation + #'RUNTIMENEW/1', # ootype operation 'COND_CALL_GC_WB', # [objptr, newvalue] (for the write barrier) 'DEBUG_MERGE_POINT/1', # debugging only - 'VIRTUAL_REF_FINISH/2', + 'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend '_CANRAISE_FIRST', # ----- start of can_raise operations ----- 'CALL', 'CALL_ASSEMBLER', 'CALL_MAY_FORCE', 'CALL_LOOPINVARIANT', - 'OOSEND', # ootype operation + #'OOSEND', # ootype operation + #'OOSEND_PURE', # ootype operation + 'CALL_PURE', # removed before it's passed to the backend + # CALL_PURE(result, func, arg_1,..,arg_n) '_CANRAISE_LAST', # ----- end of can_raise operations ----- '_OVF_FIRST', # ----- start of is_ovf operations ----- Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/resume.py Fri Jun 18 20:55:39 2010 @@ -1,10 +1,12 @@ import sys, os -from pypy.jit.metainterp.history import Box, Const, ConstInt, INT, REF +from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat +from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import jitprof -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rlib import rarithmetic -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print @@ -21,26 +23,29 @@ self.boxes = boxes class FrameInfo(object): - __slots__ = ('prev', 'jitcode', 'pc', 'exception_target') + __slots__ = ('prev', 'jitcode', 'pc') - def __init__(self, prev, frame): + def __init__(self, prev, jitcode, pc): self.prev = prev - self.jitcode = frame.jitcode - self.pc = frame.pc - self.exception_target = frame.exception_target + self.jitcode = jitcode + self.pc = pc def _ensure_parent_resumedata(framestack, n): target = framestack[n] - if n == 0 or target.parent_resumedata_frame_info_list is not None: + if n == 0: return - _ensure_parent_resumedata(framestack, n-1) back = framestack[n-1] + if target.parent_resumedata_frame_info_list is not None: + assert target.parent_resumedata_frame_info_list.pc == back.pc + return + _ensure_parent_resumedata(framestack, n-1) target.parent_resumedata_frame_info_list = FrameInfo( back.parent_resumedata_frame_info_list, - back) + back.jitcode, + back.pc) target.parent_resumedata_snapshot = Snapshot( back.parent_resumedata_snapshot, - back.env[:]) + back.get_list_of_active_boxes(True)) def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, storage): @@ -48,12 +53,15 @@ top = framestack[n] _ensure_parent_resumedata(framestack, n) frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, - top) + top.jitcode, top.pc) storage.rd_frame_info_list = frame_info_list - snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:]) - snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now + snapshot = Snapshot(top.parent_resumedata_snapshot, + top.get_list_of_active_boxes(False)) if virtualizable_boxes is not None: - snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now + boxes = virtualref_boxes + virtualizable_boxes + else: + boxes = virtualref_boxes[:] + snapshot = Snapshot(snapshot, boxes) storage.rd_snapshot = snapshot class Numbering(object): @@ -182,6 +190,7 @@ n += 1 liveboxes[box] = tagged nums[i] = tagged + # numb = Numbering(numb1, nums) self.numberings[snapshot] = numb, liveboxes, v return numb, liveboxes.copy(), v @@ -388,10 +397,10 @@ class AbstractVirtualInfo(object): - def allocate(self, metainterp): - raise NotImplementedError - def setfields(self, metainterp, box, fn_decode_box): - raise NotImplementedError + #def allocate(self, metainterp): + # raise NotImplementedError + #def setfields(self, decoder, struct): + # raise NotImplementedError def equals(self, fieldnums): return tagged_list_eq(self.fieldnums, fieldnums) def set_content(self, fieldnums): @@ -405,12 +414,11 @@ self.fielddescrs = fielddescrs #self.fieldnums = ... - def setfields(self, metainterp, box, fn_decode_box): + @specialize.argtype(1) + def setfields(self, decoder, struct): for i in range(len(self.fielddescrs)): - fieldbox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETFIELD_GC, - self.fielddescrs[i], - box, fieldbox) + descr = self.fielddescrs[i] + decoder.setfield(descr, struct, self.fieldnums[i]) def debug_prints(self): assert len(self.fielddescrs) == len(self.fieldnums) @@ -424,9 +432,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.known_class = known_class - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - None, self.known_class) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_with_vtable(self.known_class) def debug_prints(self): debug_print("\tvirtualinfo", self.known_class.repr_rpython()) @@ -437,8 +445,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.typedescr = typedescr - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW, self.typedescr) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_struct(self.typedescr) def debug_prints(self): debug_print("\tvstructinfo", self.typedescr.repr_rpython()) @@ -449,117 +458,457 @@ self.arraydescr = arraydescr #self.fieldnums = ... - def allocate(self, metainterp): + @specialize.argtype(1) + def allocate(self, decoder): length = len(self.fieldnums) - return metainterp.execute_and_record(rop.NEW_ARRAY, - self.arraydescr, - ConstInt(length)) - - def setfields(self, metainterp, box, fn_decode_box): - for i in range(len(self.fieldnums)): - itembox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETARRAYITEM_GC, - self.arraydescr, - box, ConstInt(i), itembox) + return decoder.allocate_array(self.arraydescr, length) + + @specialize.argtype(1) + def setfields(self, decoder, array): + arraydescr = self.arraydescr + length = len(self.fieldnums) + # NB. the check for the kind of array elements is moved out of the loop + if arraydescr.is_array_of_pointers(): + for i in range(length): + decoder.setarrayitem_ref(arraydescr, array, i, + self.fieldnums[i]) + elif arraydescr.is_array_of_floats(): + for i in range(length): + decoder.setarrayitem_float(arraydescr, array, i, + self.fieldnums[i]) + else: + for i in range(length): + decoder.setarrayitem_int(arraydescr, array, i, + self.fieldnums[i]) def debug_prints(self): debug_print("\tvarrayinfo", self.arraydescr) for i in self.fieldnums: debug_print("\t\t", str(untag(i))) +# ____________________________________________________________ -def rebuild_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - frameinfo = storage.rd_frame_info_list - while True: - env = resumereader.consume_boxes() - f = metainterp.newframe(frameinfo.jitcode) - f.setup_resume_at_op(frameinfo.pc, frameinfo.exception_target, env) - frameinfo = frameinfo.prev - if frameinfo is None: - break - metainterp.framestack.reverse() - return virtualizable_boxes, virtualref_boxes - -def force_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - return virtualizable_boxes, virtualref_boxes, resumereader.virtuals - - -class ResumeDataReader(object): +class AbstractResumeDataReader(object): + """A base mixin containing the logic to reconstruct virtuals out of + guard failure. There are two implementations of this mixin: + ResumeDataBoxReader for when we are compiling (i.e. when we have a + metainterp), and ResumeDataDirectReader for when we are merely + blackholing and want the best performance. + """ + _mixin_ = True virtuals = None + virtual_default = None - def __init__(self, storage, liveboxes, metainterp=None): + def _init(self, cpu, storage): + self.cpu = cpu self.cur_numb = storage.rd_numb self.consts = storage.rd_consts - self.liveboxes = liveboxes - self.cpu = metainterp.cpu - self._prepare_virtuals(metainterp, storage.rd_virtuals) - self._prepare_pendingfields(metainterp, storage.rd_pendingfields) - def _prepare_virtuals(self, metainterp, virtuals): + def _prepare(self, storage): + self._prepare_virtuals(storage.rd_virtuals) + self._prepare_pendingfields(storage.rd_pendingfields) + + def _prepare_virtuals(self, virtuals): if virtuals: - v = metainterp._already_allocated_resume_virtuals - if v is not None: - self.virtuals = v - return - self.virtuals = [None] * len(virtuals) + self.virtuals = [self.virtual_default] * len(virtuals) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - self.virtuals[i] = vinfo.allocate(metainterp) + self.virtuals[i] = vinfo.allocate(self) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - vinfo.setfields(metainterp, self.virtuals[i], - self._decode_box) + vinfo.setfields(self, self.virtuals[i]) - def _prepare_pendingfields(self, metainterp, pendingfields): - if pendingfields: - if metainterp._already_allocated_resume_virtuals is not None: - return + def _prepare_pendingfields(self, pendingfields): + if pendingfields is not None: for descr, num, fieldnum in pendingfields: - box = self._decode_box(num) - fieldbox = self._decode_box(fieldnum) - metainterp.execute_and_record(rop.SETFIELD_GC, - descr, box, fieldbox) - - def consume_boxes(self): - numb = self.cur_numb - assert numb is not None - nums = numb.nums - n = len(nums) - boxes = [None] * n - for i in range(n): - boxes[i] = self._decode_box(nums[i]) - self.cur_numb = numb.prev - return boxes + struct = self.decode_ref(num) + self.setfield(descr, struct, fieldnum) + + def _prepare_next_section(self, info): + # Use info.enumerate_vars(), normally dispatching to + # pypy.jit.codewriter.jitcode. Some tests give a different 'info'. + info.enumerate_vars(self._callback_i, + self._callback_r, + self._callback_f, + self.unique_id) # <-- annotation hack + self.cur_numb = self.cur_numb.prev + + def _callback_i(self, index, register_index): + value = self.decode_int(self.cur_numb.nums[index]) + self.write_an_int(register_index, value) + + def _callback_r(self, index, register_index): + value = self.decode_ref(self.cur_numb.nums[index]) + self.write_a_ref(register_index, value) + + def _callback_f(self, index, register_index): + value = self.decode_float(self.cur_numb.nums[index]) + self.write_a_float(register_index, value) + + def done(self): + self.cpu.clear_latest_values(self.cpu.get_latest_value_count()) + +# ---------- when resuming for pyjitpl.py, make boxes ---------- + +def rebuild_from_resumedata(metainterp, storage, virtualizable_info): + resumereader = ResumeDataBoxReader(storage, metainterp) + boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info) + virtualizable_boxes, virtualref_boxes = boxes + frameinfo = storage.rd_frame_info_list + while True: + f = metainterp.newframe(frameinfo.jitcode) + f.setup_resume_at_op(frameinfo.pc) + resumereader.consume_boxes(f.get_current_position_info(), + f.registers_i, f.registers_r, f.registers_f) + frameinfo = frameinfo.prev + if frameinfo is None: + break + metainterp.framestack.reverse() + resumereader.done() + return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes + +class ResumeDataBoxReader(AbstractResumeDataReader): + unique_id = lambda: None - def _decode_box(self, tagged): + def __init__(self, storage, metainterp): + self._init(metainterp.cpu, storage) + self.metainterp = metainterp + self.liveboxes = [None] * metainterp.cpu.get_latest_value_count() + self._prepare(storage) + + def consume_boxes(self, info, boxes_i, boxes_r, boxes_f): + self.boxes_i = boxes_i + self.boxes_r = boxes_r + self.boxes_f = boxes_f + self._prepare_next_section(info) + + def consume_virtualizable_boxes(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], and use it to know how many + # boxes of which type we have to return. This does not write + # anything into the virtualizable. + virtualizablebox = self.decode_ref(nums[-1]) + virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox) + return vinfo.load_list_of_boxes(virtualizable, self, nums) + + def consume_virtualref_boxes(self, nums, end): + # Returns a list of boxes, assumed to be all BoxPtrs. + # We leave up to the caller to call vrefinfo.continue_tracing(). + assert (end & 1) == 0 + return [self.decode_ref(nums[i]) for i in range(end)] + + def consume_vref_and_vable_boxes(self, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if vinfo is None: + virtualizable_boxes = None + end = len(nums) + else: + virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums) + end = len(nums) - len(virtualizable_boxes) + virtualref_boxes = self.consume_virtualref_boxes(nums, end) + return virtualizable_boxes, virtualref_boxes + + def allocate_with_vtable(self, known_class): + return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE, + None, known_class) + + def allocate_struct(self, typedescr): + return self.metainterp.execute_and_record(rop.NEW, typedescr) + + def allocate_array(self, arraydescr, length): + return self.metainterp.execute_and_record(rop.NEW_ARRAY, + arraydescr, ConstInt(length)) + + def setfield(self, descr, structbox, fieldnum): + if descr.is_pointer_field(): + kind = REF + elif descr.is_float_field(): + kind = FLOAT + else: + kind = INT + fieldbox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETFIELD_GC, descr, + structbox, fieldbox) + + def setarrayitem_int(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, INT) + + def setarrayitem_ref(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, REF) + + def setarrayitem_float(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, FLOAT) + + def setarrayitem(self, arraydescr, arraybox, index, fieldnum, kind): + itembox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETARRAYITEM_GC, + arraydescr, arraybox, + ConstInt(index), itembox) + + def decode_int(self, tagged): + return self.decode_box(tagged, INT) + def decode_ref(self, tagged): + return self.decode_box(tagged, REF) + def decode_float(self, tagged): + return self.decode_box(tagged, FLOAT) + + def decode_box(self, tagged, kind): num, tag = untag(tagged) if tag == TAGCONST: if tagged_eq(tagged, NULLREF): - return self.cpu.ts.CONST_NULL - return self.consts[num] + box = self.cpu.ts.CONST_NULL + else: + box = self.consts[num] elif tag == TAGVIRTUAL: virtuals = self.virtuals assert virtuals is not None - return virtuals[num] + box = virtuals[num] + elif tag == TAGINT: + box = ConstInt(num) + else: + assert tag == TAGBOX + box = self.liveboxes[num] + if box is None: + box = self.load_box_from_cpu(num, kind) + assert box.type == kind + return box + + def load_box_from_cpu(self, num, kind): + if num < 0: + num += len(self.liveboxes) + assert num >= 0 + if kind == INT: + box = BoxInt(self.cpu.get_latest_value_int(num)) + elif kind == REF: + box = BoxPtr(self.cpu.get_latest_value_ref(num)) + elif kind == FLOAT: + box = BoxFloat(self.cpu.get_latest_value_float(num)) + else: + assert 0, "bad kind: %d" % ord(kind) + self.liveboxes[num] = box + return box + + def decode_box_of_type(self, TYPE, tagged): + kind = getkind(TYPE) + if kind == 'int': kind = INT + elif kind == 'ref': kind = REF + elif kind == 'float': kind = FLOAT + else: raise AssertionError(kind) + return self.decode_box(tagged, kind) + decode_box_of_type._annspecialcase_ = 'specialize:arg(1)' + + def write_an_int(self, index, box): + self.boxes_i[index] = box + def write_a_ref(self, index, box): + self.boxes_r[index] = box + def write_a_float(self, index, box): + self.boxes_f[index] = box + +# ---------- when resuming for blackholing, get direct values ---------- + +def blackhole_from_resumedata(blackholeinterpbuilder, storage, + all_virtuals=None): + resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, + all_virtuals) + vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + # + # First get a chain of blackhole interpreters whose length is given + # by the depth of rd_frame_info_list. The first one we get must be + # the bottom one, i.e. the last one in the chain, in order to make + # the comment in BlackholeInterpreter.setposition() valid. + nextbh = None + frameinfo = storage.rd_frame_info_list + while True: + curbh = blackholeinterpbuilder.acquire_interp() + curbh.nextblackholeinterp = nextbh + nextbh = curbh + frameinfo = frameinfo.prev + if frameinfo is None: + break + firstbh = nextbh + # + # Now fill the blackhole interpreters with resume data. + curbh = firstbh + frameinfo = storage.rd_frame_info_list + while True: + curbh.setposition(frameinfo.jitcode, frameinfo.pc) + resumereader.consume_one_section(curbh) + curbh = curbh.nextblackholeinterp + frameinfo = frameinfo.prev + if frameinfo is None: + break + resumereader.done() + return firstbh + +def force_from_resumedata(metainterp_sd, storage): + resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) + resumereader.handling_async_forcing() + vinfo = metainterp_sd.virtualizable_info + vrefinfo = metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + return resumereader.virtuals + +class ResumeDataDirectReader(AbstractResumeDataReader): + unique_id = lambda: None + virtual_default = lltype.nullptr(llmemory.GCREF.TO) + resume_after_guard_not_forced = 0 + # 0: not a GUARD_NOT_FORCED + # 1: in handle_async_forcing + # 2: resuming from the GUARD_NOT_FORCED + + def __init__(self, cpu, storage, all_virtuals=None): + self._init(cpu, storage) + if all_virtuals is None: # common case + self._prepare(storage) + else: + # special case for resuming after a GUARD_NOT_FORCED: we already + # have the virtuals + self.resume_after_guard_not_forced = 2 + self.virtuals = all_virtuals + + def handling_async_forcing(self): + self.resume_after_guard_not_forced = 1 + + def consume_one_section(self, blackholeinterp): + self.blackholeinterp = blackholeinterp + info = blackholeinterp.get_current_position_info() + self._prepare_next_section(info) + + def consume_virtualref_info(self, vrefinfo, nums, end): + # we have to decode a list of references containing pairs + # [..., virtual, vref, ...] stopping at 'end' + assert (end & 1) == 0 + for i in range(0, end, 2): + virtual = self.decode_ref(nums[i]) + vref = self.decode_ref(nums[i+1]) + # For each pair, we store the virtual inside the vref. + vrefinfo.continue_tracing(vref, virtual) + + def consume_vable_info(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], load all other values + # from the CPU stack, and copy them into the virtualizable + if vinfo is None: + return len(nums) + virtualizable = self.decode_ref(nums[-1]) + virtualizable = vinfo.cast_gcref_to_vtype(virtualizable) + if self.resume_after_guard_not_forced == 1: + # in the middle of handle_async_forcing() + assert virtualizable.vable_token + virtualizable.vable_token = vinfo.TOKEN_NONE + else: + # just jumped away from assembler (case 4 in the comment in + # virtualizable.py) into tracing (case 2); check that vable_token + # is and stays 0. Note the call to reset_vable_token() in + # warmstate.py. + assert not virtualizable.vable_token + return vinfo.write_from_resume_data_partial(virtualizable, self, nums) + + def load_value_of_type(self, TYPE, tagged): + from pypy.jit.metainterp.warmstate import specialize_value + kind = getkind(TYPE) + if kind == 'int': + x = self.decode_int(tagged) + elif kind == 'ref': + x = self.decode_ref(tagged) + elif kind == 'float': + x = self.decode_float(tagged) + else: + raise AssertionError(kind) + return specialize_value(TYPE, x) + load_value_of_type._annspecialcase_ = 'specialize:arg(1)' + + def consume_vref_and_vable(self, vrefinfo, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if self.resume_after_guard_not_forced != 2: + end_vref = self.consume_vable_info(vinfo, nums) + self.consume_virtualref_info(vrefinfo, nums, end_vref) + + def allocate_with_vtable(self, known_class): + from pypy.jit.metainterp.executor import exec_new_with_vtable + return exec_new_with_vtable(self.cpu, known_class) + + def allocate_struct(self, typedescr): + return self.cpu.bh_new(typedescr) + + def allocate_array(self, arraydescr, length): + return self.cpu.bh_new_array(arraydescr, length) + + def setfield(self, descr, struct, fieldnum): + if descr.is_pointer_field(): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setfield_gc_r(struct, descr, newvalue) + elif descr.is_float_field(): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setfield_gc_f(struct, descr, newvalue) + else: + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setfield_gc_i(struct, descr, newvalue) + + def setarrayitem_int(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setarrayitem_gc_i(arraydescr, array, index, newvalue) + + def setarrayitem_ref(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setarrayitem_gc_r(arraydescr, array, index, newvalue) + + def setarrayitem_float(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setarrayitem_gc_f(arraydescr, array, index, newvalue) + + def decode_int(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getint() elif tag == TAGINT: - return ConstInt(num) + return num else: assert tag == TAGBOX - return self.liveboxes[num] + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_int(num) + + def decode_ref(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + if tagged_eq(tagged, NULLREF): + return self.cpu.ts.NULLREF + return self.consts[num].getref_base() + elif tag == TAGVIRTUAL: + virtuals = self.virtuals + assert virtuals is not None + return virtuals[num] + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_ref(num) + + def decode_float(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getfloat() + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_float(num) + + def write_an_int(self, index, int): + self.blackholeinterp.setarg_i(index, int) + + def write_a_ref(self, index, ref): + self.blackholeinterp.setarg_r(index, ref) + + def write_a_float(self, index, float): + self.blackholeinterp.setarg_f(index, float) # ____________________________________________________________ @@ -576,7 +925,7 @@ except AttributeError: jitcodename = str(compute_unique_id(frameinfo.jitcode)) debug_print('\tjitcode/pc', jitcodename, - frameinfo.pc, frameinfo.exception_target, + frameinfo.pc, 'at', compute_unique_id(frameinfo)) frameinfo = frameinfo.prev numb = storage.rd_numb Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/simple_optimize.py Fri Jun 18 20:55:39 2010 @@ -10,12 +10,18 @@ def transform(op): from pypy.jit.metainterp.history import AbstractDescr # change ARRAYCOPY to call, so we don't have to pass around - # unnecessary information to the backend + # unnecessary information to the backend. Do the same with VIRTUAL_REF_*. if op.opnum == rop.ARRAYCOPY: descr = op.args[0] assert isinstance(descr, AbstractDescr) - return ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) - return op + op = ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) + elif op.opnum == rop.CALL_PURE: + op = ResOperation(rop.CALL, op.args[1:], op.result, op.descr) + elif op.opnum == rop.VIRTUAL_REF: + op = ResOperation(rop.SAME_AS, [op.args[0]], op.result) + elif op.opnum == rop.VIRTUAL_REF_FINISH: + return [] + return [op] def optimize_loop(metainterp_sd, old_loops, loop): if old_loops: @@ -35,7 +41,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, memo) newboxes = modifier.finish(EMPTY_VALUES) descr.store_final_boxes(op, newboxes) - newoperations.append(transform(op)) + newoperations.extend(transform(op)) loop.operations = newoperations return None Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/specnode.py Fri Jun 18 20:55:39 2010 @@ -57,7 +57,8 @@ from pypy.jit.metainterp import executor, history, resoperation for ofs, subspecnode in self.fields: assert isinstance(ofs, history.AbstractDescr) - fieldbox = executor.execute(cpu, resoperation.rop.GETFIELD_GC, + fieldbox = executor.execute(cpu, None, + resoperation.rop.GETFIELD_GC, ofs, valuebox) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -95,7 +96,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp import executor, history, resoperation for i in range(len(self.items)): - itembox = executor.execute(cpu, resoperation.rop.GETARRAYITEM_GC, + itembox = executor.execute(cpu, None, + resoperation.rop.GETARRAYITEM_GC, self.arraydescr, valuebox, history.ConstInt(i)) subspecnode = self.items[i] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/oparser.py Fri Jun 18 20:55:39 2010 @@ -4,10 +4,11 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\ - ConstAddr, ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ + ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ LoopToken from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.typesystem import llhelper +from pypy.jit.codewriter.heaptracker import adr2int from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llstr @@ -74,8 +75,7 @@ return ConstPtr(obj) else: assert typ == 'class' - return ConstAddr(llmemory.cast_ptr_to_adr(obj), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(obj))) else: if typ == 'ptr': return ConstObj(obj) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_basic.py Fri Jun 18 20:55:39 2010 @@ -4,30 +4,97 @@ from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp import support, codewriter, pyjitpl, history -from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy +from pypy.jit.metainterp import pyjitpl, history +from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy from pypy import conftest from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype -def _get_bare_metainterp(func, values, CPUClass, type_system, - listops=False): - from pypy.annotation.policy import AnnotatorPolicy - from pypy.annotation.model import lltype_to_annotation - from pypy.rpython.test.test_llinterp import gengraph +def _get_jitcodes(testself, CPUClass, func, values, type_system): + from pypy.jit.codewriter import support, codewriter + from pypy.jit.metainterp import simple_optimize - rtyper = support.annotate(func, values, type_system=type_system) + class FakeWarmRunnerState: + def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): + pass + + # pick the optimizer this way + optimize_loop = staticmethod(simple_optimize.optimize_loop) + optimize_bridge = staticmethod(simple_optimize.optimize_bridge) + trace_limit = sys.maxint + debug_level = 2 + + func._jit_unroll_safe_ = True + rtyper = support.annotate(func, values, type_system=type_system) + graphs = rtyper.annotator.translator.graphs stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - graphs = rtyper.annotator.translator.graphs - opt = history.Options(listops=listops) - metainterp_sd = pyjitpl.MetaInterpStaticData(graphs[0], cpu, stats, opt) - metainterp_sd.finish_setup(optimizer="bogus") + cw = codewriter.CodeWriter(cpu, graphs[0]) + testself.cw = cw + cw.find_all_graphs(JitPolicy()) + # + testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate.cpu = cpu + if hasattr(testself, 'finish_setup_for_interp_operations'): + testself.finish_setup_for_interp_operations() + # + cw.make_jitcodes(verbose=True) + +def _run_with_blackhole(testself, args): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + cw = testself.cw + blackholeinterpbuilder = BlackholeInterpBuilder(cw) + blackholeinterp = blackholeinterpbuilder.acquire_interp() + count_i = count_r = count_f = 0 + for value in args: + T = lltype.typeOf(value) + if T == lltype.Signed: + blackholeinterp.setarg_i(count_i, value) + count_i += 1 + elif T == llmemory.GCREF: + blackholeinterp.setarg_r(count_r, value) + count_r += 1 + elif T == lltype.Float: + blackholeinterp.setarg_f(count_f, value) + count_f += 1 + else: + raise TypeError(T) + blackholeinterp.setposition(cw.mainjitcode, 0) + blackholeinterp.run() + return blackholeinterp._final_result_anytype() + +def _run_with_pyjitpl(testself, args): + + class DoneWithThisFrame(Exception): + pass + + class DoneWithThisFrameRef(DoneWithThisFrame): + def __init__(self, cpu, *args): + DoneWithThisFrame.__init__(self, *args) + + cw = testself.cw + opt = history.Options(listops=True) + metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) + metainterp_sd.finish_setup(cw, optimizer="bogus") + metainterp_sd.state = testself.warmrunnerstate + metainterp_sd.state.cpu = metainterp_sd.cpu metainterp = pyjitpl.MetaInterp(metainterp_sd) - return metainterp, rtyper + metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame + metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef + metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame + testself.metainterp = metainterp + try: + metainterp.compile_and_run_once(*args) + except DoneWithThisFrame, e: + #if conftest.option.view: + # metainterp.stats.view() + return e.args[0] + else: + raise Exception("FAILED") + class JitMixin: basic = True @@ -63,56 +130,14 @@ return ll_meta_interp(*args, **kwds) def interp_operations(self, f, args, **kwds): - from pypy.jit.metainterp import simple_optimize - - class DoneWithThisFrame(Exception): - pass - - class DoneWithThisFrameRef(DoneWithThisFrame): - def __init__(self, cpu, *args): - DoneWithThisFrame.__init__(self, *args) - - class FakeWarmRunnerState: - def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): - pass - - # pick the optimizer this way - optimize_loop = staticmethod(simple_optimize.optimize_loop) - optimize_bridge = staticmethod(simple_optimize.optimize_bridge) - - trace_limit = sys.maxint - debug_level = 2 - - metainterp, rtyper = _get_bare_metainterp(f, args, self.CPUClass, - self.type_system, - **kwds) - metainterp.staticdata.state = FakeWarmRunnerState() - metainterp.staticdata.state.cpu = metainterp.staticdata.cpu - if hasattr(self, 'finish_metainterp_for_interp_operations'): - self.finish_metainterp_for_interp_operations(metainterp) - portal_graph = rtyper.annotator.translator.graphs[0] - cw = codewriter.CodeWriter(rtyper) - - graphs = cw.find_all_graphs(portal_graph, JitPolicy(), - self.CPUClass.supports_floats) - cw._start(metainterp.staticdata, None) - portal_graph.func._jit_unroll_safe_ = True - maingraph = cw.make_one_bytecode((portal_graph, None), False) - cw.finish_making_bytecodes() - metainterp.staticdata.portal_code = maingraph - metainterp.staticdata._class_sizes = cw.class_sizes - metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame - metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef - metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame - self.metainterp = metainterp - try: - metainterp.compile_and_run_once(*args) - except DoneWithThisFrame, e: - #if conftest.option.view: - # metainterp.stats.view() - return e.args[0] - else: - raise Exception("FAILED") + # get the JitCodes for the function f + _get_jitcodes(self, self.CPUClass, f, args, self.type_system) + # try to run it with blackhole.py + result1 = _run_with_blackhole(self, args) + # try to run it with pyjitpl.py + result2 = _run_with_pyjitpl(self, args) + assert result1 == result2 + return result1 def check_history(self, expected=None, **isns): # this can be used after calling meta_interp @@ -120,6 +145,9 @@ def check_operations_history(self, expected=None, **isns): # this can be used after interp_operations + if expected is not None: + expected = dict(expected) + expected['jump'] = 1 self.metainterp.staticdata.stats.check_history(expected, **isns) @@ -151,7 +179,7 @@ class OOJitMixin(JitMixin): type_system = 'ootype' - CPUClass = runner.OOtypeCPU + #CPUClass = runner.OOtypeCPU def setup_class(cls): py.test.skip("ootype tests skipped for now") @@ -204,10 +232,12 @@ from pypy.rlib.rarithmetic import r_uint def f(a, b): + a = r_uint(a) + b = r_uint(b) return a/b - res = self.interp_operations(f, [r_uint(4), r_uint(3)]) - assert res == 1 + res = self.interp_operations(f, [-4, 3]) + assert res == long(r_uint(-4)) // 3 def test_direct_call(self): def g(n): @@ -337,7 +367,74 @@ return externfn(n, n+1) res = self.interp_operations(f, [6]) assert res == 42 - self.check_operations_history(int_add=0, int_mul=0, call=0) + # CALL_PURE is not recorded in the history if all-constant args + self.check_operations_history(int_add=0, int_mul=0, + call=0, call_pure=0) + + def test_residual_call_pure_1(self): + def externfn(x, y): + return x * y + externfn._pure_function_ = True + def f(n): + return externfn(n, n+1) + res = self.interp_operations(f, [6]) + assert res == 42 + # CALL_PURE is recorded in the history if not-all-constant args + self.check_operations_history(int_add=1, int_mul=0, + call=0, call_pure=1) + + def test_residual_call_pure_2(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + def externfn(x): + return x - 1 + externfn._pure_function_ = True + def f(n): + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + n = externfn(n) + return n + res = self.meta_interp(f, [7]) + assert res == 0 + # CALL_PURE is recorded in the history, but turned into a CALL + # by optimizeopt.py + self.check_loops(int_sub=0, call=1, call_pure=0) + + def test_constfold_call_pure(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + n -= externfn(m) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) + + def test_constfold_call_pure_2(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + class V: + def __init__(self, value): + self.value = value + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + v = V(m) + n -= externfn(v.value) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) @@ -444,6 +541,76 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_uint_operations(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + res = self.interp_operations(f, [50]) + assert res == False + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + + def test_uint_condition(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + if ((r_uint(n) - 123) >> 1) <= r_uint(456): + return 24 + else: + return 12 + res = self.interp_operations(f, [50]) + assert res == 12 + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + + def test_int_between(self): + # + def check(arg1, arg2, arg3, expect_result, **expect_operations): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop + loc = locals().copy() + exec py.code.Source(""" + def f(n, m, p): + arg1 = %(arg1)s + arg2 = %(arg2)s + arg3 = %(arg3)s + return llop.int_between(lltype.Bool, arg1, arg2, arg3) + """ % locals()).compile() in loc + res = self.interp_operations(loc['f'], [5, 6, 7]) + assert res == expect_result + self.check_operations_history(expect_operations) + # + check('n', 'm', 'p', True, int_sub=2, uint_lt=1) + check('n', 'p', 'm', False, int_sub=2, uint_lt=1) + # + check('n', 'm', 6, False, int_sub=2, uint_lt=1) + # + check('n', 4, 'p', False, int_sub=2, uint_lt=1) + check('n', 5, 'p', True, int_sub=2, uint_lt=1) + check('n', 8, 'p', False, int_sub=2, uint_lt=1) + # + check('n', 6, 7, True, int_sub=2, uint_lt=1) + # + check(-2, 'n', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'm', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'p', 'm', False, int_sub=2, uint_lt=1) + #check(0, 'n', 'p', True, uint_lt=1) xxx implement me + #check(0, 'm', 'p', True, uint_lt=1) + #check(0, 'p', 'm', False, uint_lt=1) + # + check(2, 'n', 6, True, int_sub=1, uint_lt=1) + check(2, 'm', 6, False, int_sub=1, uint_lt=1) + check(2, 'p', 6, False, int_sub=1, uint_lt=1) + check(5, 'n', 6, True, int_eq=1) # 6 == 5+1 + check(5, 'm', 6, False, int_eq=1) # 6 == 5+1 + # + check(2, 6, 'm', False, int_sub=1, uint_lt=1) + check(2, 6, 'p', True, int_sub=1, uint_lt=1) + # + check(2, 40, 6, False) + check(2, 40, 60, True) + def test_getfield(self): class A: pass @@ -513,6 +680,39 @@ res = self.interp_operations(f, [15]) assert res == -1 + def test_int_add_ovf(self): + def f(x, y): + try: + return ovfcheck(x + y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -98 + res = self.interp_operations(f, [1, sys.maxint]) + assert res == -42 + + def test_int_sub_ovf(self): + def f(x, y): + try: + return ovfcheck(x - y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -102 + res = self.interp_operations(f, [1, -sys.maxint]) + assert res == -42 + + def test_int_mul_ovf(self): + def f(x, y): + try: + return ovfcheck(x * y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -200 + res = self.interp_operations(f, [-3, sys.maxint//2]) + assert res == -42 + def test_mod_ovf(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) def f(n, x, y): @@ -523,6 +723,7 @@ return n res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + self.check_loops(call=0) def test_abs(self): myjitdriver = JitDriver(greens = [], reds = ['i', 't']) @@ -581,10 +782,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) def test_bridge_from_interpreter_2(self): # one case for backend - computing of framesize on guard failure @@ -731,21 +931,26 @@ def test_zerodivisionerror(self): # test the case of exception-raising operation that is not delegated # to the backend at all: ZeroDivisionError - from pypy.rpython.lltypesystem.lloperation import llop # def f(n): + assert n >= 0 try: - return llop.int_mod_ovf_zer(lltype.Signed, 5, n) + return ovfcheck(5 % n) except ZeroDivisionError: return -666 + except OverflowError: + return -777 res = self.interp_operations(f, [0]) assert res == -666 # def f(n): + assert n >= 0 try: - return llop.int_floordiv_ovf_zer(lltype.Signed, 6, n) + return ovfcheck(6 // n) except ZeroDivisionError: return -667 + except OverflowError: + return -778 res = self.interp_operations(f, [0]) assert res == -667 @@ -795,7 +1000,7 @@ assert not res def test_isinstance_2(self): - driver = JitDriver(greens = [], reds = ['x', 'n', 'sum']) + driver = JitDriver(greens = [], reds = ['n', 'sum', 'x']) class A: pass class B(A): @@ -836,7 +1041,9 @@ return obj.a res = self.interp_operations(fn, [1]) assert res == 1 - self.check_operations_history(guard_class=0, instanceof=0) + self.check_operations_history(guard_class=0) + if self.type_system == 'ootype': + self.check_operations_history(instanceof=0) def test_r_dict(self): from pypy.rlib.objectmodel import r_dict @@ -1017,10 +1224,10 @@ def test_residual_external_call(self): import math - myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res']) def f(x, y): x = float(x) - res = 0 + res = 0.0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) @@ -1259,7 +1466,7 @@ self.check_loops(call=1) def test_bug_optimizeopt_mutates_ops(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'a', 'const']) + myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a']) class A(object): pass class B(A): @@ -1326,6 +1533,16 @@ # this checks that the logic triggered by make_a_counter_per_value() # works and prevents generating tons of bridges + def test_swap_values(self): + def f(x, y): + if x > 5: + x, y = y, x + return x - y + res = self.interp_operations(f, [10, 2]) + assert res == -8 + res = self.interp_operations(f, [3, 2]) + assert res == 1 + class TestOOtype(BasicTests, OOJitMixin): @@ -1426,33 +1643,47 @@ from pypy.rpython.lltypesystem import lltype TP = lltype.Struct('x') - def f(p1, p2): + def f(i1, i2): + p1 = prebuilt[i1] + p2 = prebuilt[i2] a = p1 is p2 b = p1 is not p2 c = bool(p1) d = not bool(p2) return 1000*a + 100*b + 10*c + d - x = lltype.malloc(TP, flavor='raw') - expected = f(x, x) - assert self.interp_operations(f, [x, x]) == expected - lltype.free(x, flavor='raw') + prebuilt = [lltype.malloc(TP, flavor='raw')] * 2 + expected = f(0, 1) + assert self.interp_operations(f, [0, 1]) == expected def test_casts(self): + py.test.skip("xxx fix or kill") if not self.basic: py.test.skip("test written in a style that " "means it's frontend only") - from pypy.rpython.lltypesystem import lltype, llmemory - - TP = lltype.GcStruct('x') + from pypy.rpython.lltypesystem import lltype, llmemory, rffi + + TP = lltype.GcStruct('S1') def f(p): n = lltype.cast_ptr_to_int(p) return n - x = lltype.malloc(TP) - res = self.interp_operations(f, [x]) - expected = self.metainterp.cpu.do_cast_ptr_to_int( - history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))).value - assert res == expected + xref = lltype.cast_opaque_ptr(llmemory.GCREF, x) + res = self.interp_operations(f, [xref]) + y = llmemory.cast_ptr_to_adr(x) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) + # + TP = lltype.Struct('S2') + prebuilt = [lltype.malloc(TP, immortal=True), + lltype.malloc(TP, immortal=True)] + def f(x): + p = prebuilt[x] + n = lltype.cast_ptr_to_int(p) + return n + res = self.interp_operations(f, [1]) + y = llmemory.cast_ptr_to_adr(prebuilt[1]) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) def test_collapsing_ptr_eq(self): S = lltype.GcStruct('S') Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_blackhole.py Fri Jun 18 20:55:39 2010 @@ -1,87 +1,211 @@ +import py from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp import pyjitpl +from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder +from pypy.jit.metainterp.blackhole import BlackholeInterpreter +from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl +from pypy.jit.metainterp import history, pyjitpl +from pypy.jit.codewriter.assembler import JitCode +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.llinterp import LLException -class BlackholeTests(object): - - def meta_interp(self, *args): - def counting_init(frame, metainterp, jitcode, greenkey=None): - previnit(frame, metainterp, jitcode, greenkey) - self.seen_frames.append(jitcode.name) +class FakeCodeWriter: + pass +class FakeAssembler: + pass +class FakeCPU: + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert func == 321 + assert calldescr == "" + if args_i[0] < 0: + raise LLException("etype", "evalue") + return args_i[0] * 2 + +def getblackholeinterp(insns, descrs=[]): + cw = FakeCodeWriter() + cw.cpu = FakeCPU() + cw.assembler = FakeAssembler() + cw.assembler.insns = insns + cw.assembler.descrs = descrs + builder = BlackholeInterpBuilder(cw) + return builder.acquire_interp() + +def test_simple(): + jitcode = JitCode("test") + jitcode.setup("\x00\x00\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_add/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0, 40) + blackholeinterp.setarg_i(1, 2) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_const(): + jitcode = JitCode("test") + jitcode.setup("\x00\x30\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_sub/ci>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 6) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_bigconst(): + jitcode = JitCode("test") + jitcode.setup("\x00\xFD\x01\x02" + "\x01\x02", + [666, 666, 10042, 666]) + blackholeinterp = getblackholeinterp({'int_sub/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 10000) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_loop(): + jitcode = JitCode("test") + jitcode.setup("\x00\x16\x02\x10\x00" # L1: goto_if_not_int_gt %i0, 2, L2 + "\x01\x17\x16\x17" # int_add %i1, %i0, %i1 + "\x02\x16\x01\x16" # int_sub %i0, $1, %i0 + "\x03\x00\x00" # goto L1 + "\x04\x17", # L2: int_return %i1 + []) + blackholeinterp = getblackholeinterp({'goto_if_not_int_gt/icL': 0, + 'int_add/ii>i': 1, + 'int_sub/ic>i': 2, + 'goto/L': 3, + 'int_return/i': 4}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x16, 6) # %i0 + blackholeinterp.setarg_i(0x17, 100) # %i1 + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 100+6+5+4+3 + +def test_simple_exception(): + jitcode = JitCode("test") + jitcode.setup( # residual_call_ir_i $<* fn g>, , I[%i9], R[], %i8 + "\x01\xFF\x00\x00\x01\x09\x00\x08" + "\x00\x0D\x00" # catch_exception L1 + "\x02\x08" # int_return %i8 + "\x03\x2A", # L1: int_return $42 + [321]) # <-- address of the function g + blackholeinterp = getblackholeinterp({'catch_exception/L': 0, + 'residual_call_ir_i/idIR>i': 1, + 'int_return/i': 2, + 'int_return/c': 3}, + [""]) + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, 100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 200 + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, -100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_convert_and_run_from_pyjitpl(): + class MyMIFrame: + jitcode = JitCode("test") + jitcode.setup("\xFF" # illegal instruction + "\x00\x00\x01\x02" # int_add/ii>i + "\x01\x02", # int_return/i + [], + num_regs_i=3, num_regs_r=0, num_regs_f=0) + pc = 1 + registers_i = [history.BoxInt(40), history.ConstInt(2), None] + class MyMetaInterp: + class staticdata: + result_type = 'int' + class profiler: + @staticmethod + def start_blackhole(): pass + @staticmethod + def end_blackhole(): pass + class DoneWithThisFrameInt(Exception): + pass + last_exc_value_box = None + framestack = [MyMIFrame()] + MyMetaInterp.staticdata.blackholeinterpbuilder = getblackholeinterp( + {'int_add/ii>i': 0, 'int_return/i': 1}).builder + MyMetaInterp.staticdata.blackholeinterpbuilder.metainterp_sd = \ + MyMetaInterp.staticdata + # + d = py.test.raises(MyMetaInterp.staticdata.DoneWithThisFrameInt, + convert_and_run_from_pyjitpl, MyMetaInterp()) + assert d.value.args == (42,) + + +class TestBlackhole(LLJitMixin): + + def test_blackholeinterp_cache(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + def choices(x): + if x == 2: return 10 + if x == 3: return 199 + if x == 4: return 124 + if x == 5: return -521 + if x == 6: return 8917 + if x == 7: return -387 + return 34871 + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + y += choices(x) + x -= 1 + return y # - previnit = pyjitpl.MIFrame.__init__.im_func + seen = [] + def my_copy_constants(self, *args): + seen.append(1) + return org_copy_constants(self, *args) + org_copy_constants = BlackholeInterpreter.copy_constants + BlackholeInterpreter.copy_constants = my_copy_constants try: - self.seen_frames = [] - pyjitpl.MIFrame.__init__ = counting_init - return super(BlackholeTests, self).meta_interp(*args) + res = self.meta_interp(f, [7], repeat=7) finally: - pyjitpl.MIFrame.__init__ = previnit - - def test_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - return g() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_indirect_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - call = h - else: - call = g - return call() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_oosends_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - class A: - def meth(self): - return 42 - class B(A): - def meth(self): - return 45 - class C(A): - def meth(self): - return 64 - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - x = B() - else: - x = C() - return x.meth() - res = self.meta_interp(f, [7]) - assert res == 64 - assert self.seen_frames == ['f', 'f'] - - -class TestLLtype(BlackholeTests, LLJitMixin): - pass - -class TestOOtype(BlackholeTests, OOJitMixin): - pass + BlackholeInterpreter.copy_constants = org_copy_constants + # + assert res == sum([choices(x) for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 + assert len(seen) == 2 * 3 + + def test_blackholeinterp_cache_exc(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + class FooError(Exception): + def __init__(self, num): + self.num = num + def choices(x): + if x == 2: raise FooError(10) + if x == 3: raise FooError(199) + if x == 4: raise FooError(124) + if x == 5: raise FooError(-521) + if x == 6: raise FooError(8917) + if x == 7: raise FooError(-387) + raise FooError(34871) + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + try: + choices(x) + except FooError, e: + y += e.num + x -= 1 + return y + res = self.meta_interp(f, [7], repeat=7) + assert res == sum([py.test.raises(FooError, choices, x).value.num + for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_compile.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,8 @@ from pypy.jit.metainterp.history import BoxInt from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop -from pypy.jit.metainterp.compile import ResumeGuardDescr, ResumeGuardCounters +from pypy.jit.metainterp.compile import ResumeGuardDescr +from pypy.jit.metainterp.compile import ResumeGuardCountersInt from pypy.jit.metainterp import optimize, jitprof, typesystem from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin @@ -107,49 +108,49 @@ def test_resume_guard_counters(): - rgc = ResumeGuardCounters() + rgc = ResumeGuardCountersInt() # fill in the table for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 1 - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 2 assert rgc.counters == [0] * (4-i) + [2] * (1+i) for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 3 # make a distribution: [5, 4, 7, 6, 3] assert rgc.counters == [3, 3, 3, 3, 3] - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 4 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 5 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 4 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 5 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 7 - count = rgc.see(BoxInt(103)) + count = rgc.see_int(103) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 5 assert rgc.counters == [5, 4, 7, 6, 3] # the next new item should throw away 104, as 5 is the middle counter - count = rgc.see(BoxInt(190)) + count = rgc.see_int(190) assert count == 1 assert rgc.counters == [1, 4, 7, 6, 3] # the next new item should throw away 103, as 4 is the middle counter - count = rgc.see(BoxInt(191)) + count = rgc.see_int(191) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 3] # the next new item should throw away 100, as 3 is the middle counter - count = rgc.see(BoxInt(192)) + count = rgc.see_int(192) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 1] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_exception.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,7 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy class ExceptionTests: @@ -516,11 +516,10 @@ assert res == -1 self.check_tree_loop_count(2) # the loop and the entry path # we get: - # ENTER - compile the new loop - # ENTER (BlackHole) - leave - # ENTER - compile the entry bridge - # ENTER - compile the leaving path (raising MyError) - self.check_enter_count(4) + # ENTER - compile the new loop + # ENTER - compile the entry bridge + # ENTER - compile the leaving path (raising MyError) + self.check_enter_count(3) def test_bridge_from_interpreter_exc_2(self): @@ -556,7 +555,6 @@ optimizer=OPTIMIZER_SIMPLE) assert res == 8 - def test_overflowerror_escapes(self): def g(x): return ovfcheck(x + 1) @@ -570,6 +568,26 @@ res = self.interp_operations(f, [sys.maxint]) assert res == -42 + def test_bug_1(self): + def h(i): + if i > 10: + raise ValueError + if i > 5: + raise KeyError + return 5 + def g(i): + try: + return h(i) + except ValueError: + return 21 + def f(i): + try: + return g(i) + except KeyError: + return 42 + res = self.interp_operations(f, [99]) + assert res == 21 + class MyError(Exception): def __init__(self, n): self.n = n Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_executor.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_executor.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_executor.py Fri Jun 18 20:55:39 2010 @@ -1,60 +1,87 @@ import py import sys, random from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.jit.metainterp.executor import make_execute_list, execute +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.executor import execute_varargs, execute_nonspec from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat from pypy.jit.metainterp.history import AbstractDescr, Box +from pypy.jit.metainterp import history from pypy.jit.backend.model import AbstractCPU class FakeDescr(AbstractDescr): pass -class FakeBox(Box): +class FakeCallDescr(FakeDescr): + def get_return_type(self): + return history.FLOAT + +class FakeFieldDescr(FakeDescr): + def is_pointer_field(self): + return False + def is_float_field(self): + return True + +class FakeArrayDescr(FakeDescr): + def is_array_of_pointers(self): + return False + def is_array_of_floats(self): + return True + +class FakeResultR: + _TYPE = llmemory.GCREF def __init__(self, *args): - self.args = args + self.fakeargs = args + +class FakeMetaInterp: + pass class FakeCPU(AbstractCPU): supports_floats = True - def do_new(self, descr): - return FakeBox('new', descr) - - def do_arraylen_gc(self, box1, descr): - return FakeBox('arraylen_gc', box1, descr) - - def do_setfield_gc(self, box1, box2, descr): - return FakeBox('setfield_gc', box1, box2, descr) + def bh_new(self, descr): + return FakeResultR('new', descr) - def do_setarrayitem_gc(self, box1, box2, box3, descr): - return FakeBox('setarrayitem_gc', box1, box2, box3, descr) + def bh_arraylen_gc(self, descr, array): + assert not array + assert isinstance(descr, FakeDescr) + return 55 + + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + self.fakesetfield = (struct, newvalue, fielddescr) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + self.fakesetarrayitem = (array, index, newvalue, arraydescr) + + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self.fakecalled = (func, calldescr, args_i, args_r, args_f) + return 42.5 - def do_call(self, args, descr): - return FakeBox('call', args, descr) - - def do_strsetitem(self, box1, box2, box3): - return FakeBox('strsetitem', box1, box2, box3) - -make_execute_list(FakeCPU) + def bh_strsetitem(self, string, index, newvalue): + self.fakestrsetitem = (string, index, newvalue) def test_execute(): cpu = FakeCPU() descr = FakeDescr() - box = execute(cpu, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) + box = execute(cpu, None, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) assert box.value == 42 - box = execute(cpu, rop.NEW, descr) - assert box.args == ('new', descr) + box = execute(cpu, None, rop.NEW, descr) + assert box.value.fakeargs == ('new', descr) def test_execute_varargs(): cpu = FakeCPU() - descr = FakeDescr() - argboxes = [BoxInt(321), ConstInt(123)] - box = execute_varargs(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + descr = FakeCallDescr() + argboxes = [BoxInt(99999), BoxInt(321), ConstFloat(2.25), ConstInt(123), + BoxPtr(), BoxFloat(5.5)] + box = execute_varargs(cpu, FakeMetaInterp(), rop.CALL, argboxes, descr) + assert box.value == 42.5 + assert cpu.fakecalled == (99999, descr, [321, 123], + [ConstPtr.value], [2.25, 5.5]) def test_execute_nonspec(): cpu = FakeCPU() @@ -62,33 +89,38 @@ # cases with a descr # arity == -1 argboxes = [BoxInt(321), ConstInt(123)] - box = execute_nonspec(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + box = execute_nonspec(cpu, FakeMetaInterp(), rop.CALL, + argboxes, FakeCallDescr()) + assert box.value == 42.5 # arity == 0 - box = execute_nonspec(cpu, rop.NEW, [], descr) - assert box.args == ('new', descr) + box = execute_nonspec(cpu, None, rop.NEW, [], descr) + assert box.value.fakeargs == ('new', descr) # arity == 1 - box1 = BoxInt(515) - box = execute_nonspec(cpu, rop.ARRAYLEN_GC, [box1], descr) - assert box.args == ('arraylen_gc', box1, descr) + box1 = BoxPtr() + box = execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr) + assert box.value == 55 # arity == 2 - box2 = BoxInt(222) - box = execute_nonspec(cpu, rop.SETFIELD_GC, [box1, box2], descr) - assert box.args == ('setfield_gc', box1, box2, descr) + box2 = BoxFloat(222.2) + fielddescr = FakeFieldDescr() + execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr) + assert cpu.fakesetfield == (box1.value, box2.value, fielddescr) # arity == 3 - box3 = BoxInt(-33) - box = execute_nonspec(cpu, rop.SETARRAYITEM_GC, [box1, box2, box3], descr) - assert box.args == ('setarrayitem_gc', box1, box2, box3, descr) + box3 = BoxInt(33) + arraydescr = FakeArrayDescr() + execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2], + arraydescr) + assert cpu.fakesetarrayitem == (box1.value, box3.value, box2.value, + arraydescr) # cases without descr # arity == 1 - box = execute_nonspec(cpu, rop.INT_INVERT, [box1]) - assert box.value == ~515 + box = execute_nonspec(cpu, None, rop.INT_INVERT, [box3]) + assert box.value == ~33 # arity == 2 - box = execute_nonspec(cpu, rop.INT_LSHIFT, [box1, BoxInt(3)]) - assert box.value == 515 << 3 + box = execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, BoxInt(3)]) + assert box.value == 33 << 3 # arity == 3 - box = execute_nonspec(cpu, rop.STRSETITEM, [box1, box2, box3]) - assert box.args == ('strsetitem', box1, box2, box3) + execute_nonspec(cpu, None, rop.STRSETITEM, [box1, BoxInt(3), box3]) + assert cpu.fakestrsetitem == (box1.value, 3, box3.value) # ints @@ -181,7 +213,7 @@ (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]), (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]), (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]), - (rop.BOOL_NOT, [(0, 1), (1, 0)]), + (rop.INT_IS_ZERO, [(0, 1), (1, 0), (2, 0), (-1, 0), (minint, 0)]), ]: for x, y in testcases: yield opnum, [x], y @@ -204,7 +236,7 @@ def test_int_ops(): cpu = FakeCPU() for opnum, boxargs, retvalue in get_int_tests(): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) assert box.getint() == retvalue # floats @@ -242,9 +274,6 @@ yield (rop.FLOAT_NEG, [15.9], 'float', -15.9) yield (rop.FLOAT_ABS, [-5.9], 'float', 5.9) yield (rop.FLOAT_ABS, [15.9], 'float', 15.9) - yield (rop.FLOAT_IS_TRUE, [-5.9], 'int', 1) - yield (rop.FLOAT_IS_TRUE, [0.0], 'int', 0) - yield (rop.FLOAT_IS_TRUE, [-0.0], 'int', 0) yield (rop.CAST_FLOAT_TO_INT, [-5.9], 'int', -5) yield (rop.CAST_FLOAT_TO_INT, [5.9], 'int', 5) yield (rop.CAST_INT_TO_FLOAT, [123], 'float', 123.0) @@ -276,7 +305,7 @@ def test_float_ops(): cpu = FakeCPU() for opnum, boxargs, rettype, retvalue in get_float_tests(cpu): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) if rettype == 'float': assert box.getfloat() == retvalue elif rettype == 'int': Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_history.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_history.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_history.py Fri Jun 18 20:55:39 2010 @@ -9,10 +9,3 @@ s = lltype.cast_pointer(lltype.Ptr(S), t) const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)) assert const._getrepr_() == "*T" - -def test_slicing(): - h = History() - h.operations = [1, 2, 3, 4, 5] - rest = h.slice_history_at(2) - assert rest == [4, 5] - assert h.operations == [1, 2] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_jitprof.py Fri Jun 18 20:55:39 2010 @@ -63,7 +63,7 @@ ] assert profiler.events == expected assert profiler.times == [2, 1, 1, 1] - assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0, + assert profiler.counters == [1, 1, 1, 1, 3, 3, 1, 7, 1, 0, 0, 0, 0, 0, 0, 0] def test_simple_loop_with_call(self): @@ -84,8 +84,7 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[1, 0], [1, 0], [0, 0]] + assert profiler.calls == 1 def test_blackhole_pure(self): @purefunction @@ -99,12 +98,10 @@ myjitdriver.can_enter_jit(x=x, y=y, res=res, z=z) myjitdriver.jit_merge_point(x=x, y=y, res=res, z=z) res += x - if y == 1: - res += g(z) + res += g(z) y -= 1 return res * 2 res = self.meta_interp(f, [6, 7, 2]) - assert res == 90 + assert res == f(6, 7, 2) profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[0, 1], [0, 0], [0, 1]] + assert profiler.calls == 1 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_list.py Fri Jun 18 20:55:39 2010 @@ -1,7 +1,5 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py Fri Jun 18 20:55:39 2010 @@ -2,9 +2,8 @@ from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.objectmodel import compute_hash from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats -from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import history @@ -342,7 +341,7 @@ assert res == expected def test_loop_unicode(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = u'' while n > 13: @@ -356,7 +355,7 @@ assert res == expected def test_loop_string(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = '' while n > 13: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizefindnode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizefindnode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizefindnode.py Fri Jun 18 20:55:39 2010 @@ -6,7 +6,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - Const, ConstAddr, TreeLoop, BoxObj, + Const, TreeLoop, BoxObj, ConstObj, AbstractDescr) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder @@ -16,7 +16,8 @@ from pypy.jit.metainterp.specnode import VirtualArraySpecNode from pypy.jit.metainterp.specnode import VirtualStructSpecNode from pypy.jit.metainterp.specnode import ConstantSpecNode -from pypy.jit.metainterp.effectinfo import EffectInfo +from pypy.jit.codewriter.effectinfo import EffectInfo +from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int from pypy.jit.metainterp.test.oparser import parse def test_sort_descrs(): @@ -113,7 +114,7 @@ EffectInfo([adescr], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], - forces_virtual_or_virtualizable=True)) + EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)) class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though @@ -129,83 +130,81 @@ jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) - cpu.class_sizes = { - cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE), - cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2), - cpu.cast_adr_to_int(u_vtable_adr): cpu.sizeof(U), - cpu.cast_adr_to_int(jvr_vtable_adr): cpu.sizeof( - vrefinfo.JIT_VIRTUAL_REF), - } + register_known_gctype(cpu, node_vtable, NODE) + register_known_gctype(cpu, node_vtable2, NODE2) + register_known_gctype(cpu, u_vtable, U) + register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF) + namespace = locals() -class OOtypeMixin(object): +class OOtypeMixin_xxx_disabled(object): type_system = 'ootype' - def get_class_of_box(self, box): - root = box.getref(ootype.ROOT) - return ootype.classof(root) +## def get_class_of_box(self, box): +## root = box.getref(ootype.ROOT) +## return ootype.classof(root) - cpu = runner.OOtypeCPU(None) - NODE = ootype.Instance('NODE', ootype.ROOT, {}) - NODE._add_fields({'value': ootype.Signed, - 'floatval' : ootype.Float, - 'next': NODE}) - NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) - - node_vtable = ootype.runtimeClass(NODE) - node_vtable_adr = ootype.cast_to_object(node_vtable) - node_vtable2 = ootype.runtimeClass(NODE2) - node_vtable_adr2 = ootype.cast_to_object(node_vtable2) - - node = ootype.new(NODE) - nodebox = BoxObj(ootype.cast_to_object(node)) - myptr = nodebox.value - myptr2 = ootype.cast_to_object(ootype.new(NODE)) - nodebox2 = BoxObj(ootype.cast_to_object(node)) - valuedescr = cpu.fielddescrof(NODE, 'value') - floatdescr = cpu.fielddescrof(NODE, 'floatval') - nextdescr = cpu.fielddescrof(NODE, 'next') - otherdescr = cpu.fielddescrof(NODE2, 'other') - nodesize = cpu.typedescrof(NODE) - nodesize2 = cpu.typedescrof(NODE2) - - arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) - floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) - - # a plain Record - S = ootype.Record({'a': ootype.Signed, 'b': NODE}) - ssize = cpu.typedescrof(S) - adescr = cpu.fielddescrof(S, 'a') - bdescr = cpu.fielddescrof(S, 'b') - sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) - arraydescr2 = cpu.arraydescrof(ootype.Array(S)) - - T = ootype.Record({'c': ootype.Signed, - 'd': ootype.Array(NODE)}) - tsize = cpu.typedescrof(T) - cdescr = cpu.fielddescrof(T, 'c') - ddescr = cpu.fielddescrof(T, 'd') - arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) - - U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) - usize = cpu.typedescrof(U) - onedescr = cpu.fielddescrof(U, 'one') - u_vtable = ootype.runtimeClass(U) - u_vtable_adr = ootype.cast_to_object(u_vtable) - - # force a consistent order - valuedescr.sort_key() - nextdescr.sort_key() - adescr.sort_key() - bdescr.sort_key() - - FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) - nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype - - cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), - node_vtable_adr2: cpu.typedescrof(NODE2), - u_vtable_adr: cpu.typedescrof(U)} - namespace = locals() +## cpu = runner.OOtypeCPU(None) +## NODE = ootype.Instance('NODE', ootype.ROOT, {}) +## NODE._add_fields({'value': ootype.Signed, +## 'floatval' : ootype.Float, +## 'next': NODE}) +## NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) + +## node_vtable = ootype.runtimeClass(NODE) +## node_vtable_adr = ootype.cast_to_object(node_vtable) +## node_vtable2 = ootype.runtimeClass(NODE2) +## node_vtable_adr2 = ootype.cast_to_object(node_vtable2) + +## node = ootype.new(NODE) +## nodebox = BoxObj(ootype.cast_to_object(node)) +## myptr = nodebox.value +## myptr2 = ootype.cast_to_object(ootype.new(NODE)) +## nodebox2 = BoxObj(ootype.cast_to_object(node)) +## valuedescr = cpu.fielddescrof(NODE, 'value') +## floatdescr = cpu.fielddescrof(NODE, 'floatval') +## nextdescr = cpu.fielddescrof(NODE, 'next') +## otherdescr = cpu.fielddescrof(NODE2, 'other') +## nodesize = cpu.typedescrof(NODE) +## nodesize2 = cpu.typedescrof(NODE2) + +## arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) +## floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) + +## # a plain Record +## S = ootype.Record({'a': ootype.Signed, 'b': NODE}) +## ssize = cpu.typedescrof(S) +## adescr = cpu.fielddescrof(S, 'a') +## bdescr = cpu.fielddescrof(S, 'b') +## sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) +## arraydescr2 = cpu.arraydescrof(ootype.Array(S)) + +## T = ootype.Record({'c': ootype.Signed, +## 'd': ootype.Array(NODE)}) +## tsize = cpu.typedescrof(T) +## cdescr = cpu.fielddescrof(T, 'c') +## ddescr = cpu.fielddescrof(T, 'd') +## arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) + +## U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) +## usize = cpu.typedescrof(U) +## onedescr = cpu.fielddescrof(U, 'one') +## u_vtable = ootype.runtimeClass(U) +## u_vtable_adr = ootype.cast_to_object(u_vtable) + +## # force a consistent order +## valuedescr.sort_key() +## nextdescr.sort_key() +## adescr.sort_key() +## bdescr.sort_key() + +## FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) +## nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype + +## cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), +## node_vtable_adr2: cpu.typedescrof(NODE2), +## u_vtable_adr: cpu.typedescrof(U)} +## namespace = locals() class BaseTest(object): invent_fail_descr = None @@ -220,8 +219,7 @@ # def constclass(cls_vtable): if self.type_system == 'lltype': - return ConstAddr(llmemory.cast_ptr_to_adr(cls_vtable), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable))) else: return ConstObj(ootype.cast_to_object(cls_vtable)) def constant(value): @@ -357,7 +355,7 @@ assert not boxp2.fromstart assert boxp1.knownclsbox is None - assert boxp2.knownclsbox.value == self.node_vtable_adr + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr def test_find_nodes_new_2(self): ops = """ @@ -413,8 +411,8 @@ assert not boxp2.fromstart assert not boxp3.fromstart - assert boxp2.knownclsbox.value == self.node_vtable_adr - assert boxp3.knownclsbox.value == self.node_vtable_adr2 + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr + assert boxp3.knownclsbox.getaddr() == self.node_vtable_adr2 def test_find_nodes_new_aliasing_0(self): ops = """ @@ -503,31 +501,31 @@ nextdescr=Virtual(node_vtable, nextdescr=Virtual(node_vtable)))''') - def test_find_nodes_oois(self): + def test_find_nodes_ptr_eq(self): ops = """ [p3, p4, p2] p0 = new_with_vtable(ConstClass(node_vtable)) p1 = new_with_vtable(ConstClass(node_vtable)) guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -1160,14 +1158,13 @@ class TestLLtype(BaseTestOptimizeFindNode, LLtypeMixin): pass -class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): - - def test_find_nodes_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - boxes, getnode = self.find_nodes(ops, 'Not') - assert not getnode(boxes.p0).escaped +##class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): +## def test_find_nodes_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## boxes, getnode = self.find_nodes(ops, 'Not') +## assert not getnode(boxes.p0).escaped Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py Fri Jun 18 20:55:39 2010 @@ -1,8 +1,7 @@ import py from pypy.rlib.objectmodel import instantiate -from pypy.jit.metainterp.test.test_resume import MyMetaInterp from pypy.jit.metainterp.test.test_optimizefindnode import (LLtypeMixin, - OOtypeMixin, + #OOtypeMixin, BaseTest) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp import optimizeopt @@ -10,18 +9,17 @@ from pypy.jit.metainterp.optimizeutil import InvalidLoop from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from pypy.jit.metainterp.jitprof import EmptyProfiler -from pypy.jit.metainterp import executor, compile, resume +from pypy.jit.metainterp import executor, compile, resume, history from pypy.jit.metainterp.resoperation import rop, opname, ResOperation from pypy.jit.metainterp.test.oparser import pure_parse -class FakeFrame(object): - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - - def __init__(self, code="", pc=0, exc_target=-1): - self.jitcode = code - self.pc = pc - self.exception_target = exc_target +##class FakeFrame(object): +## parent_resumedata_snapshot = None +## parent_resumedata_frame_info_list = None + +## def __init__(self, code="", pc=0): +## self.jitcode = code +## self.pc = pc class Fake(object): failargs_limit = 1000 @@ -45,9 +43,8 @@ fdescr = ResumeGuardDescr(None, None) op = ResOperation(rop.GUARD_TRUE, [], None, descr=fdescr) # setup rd data - fi0 = resume.FrameInfo(None, FakeFrame("code0", 1, 2)) - fdescr.rd_frame_info_list = resume.FrameInfo(fi0, - FakeFrame("code1", 3, -1)) + fi0 = resume.FrameInfo(None, "code0", 11) + fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) snapshot0 = resume.Snapshot(None, [b0]) fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1]) # @@ -215,14 +212,18 @@ def __eq__(self, other): return type(self) is type(other) # xxx obscure +def _sortboxes(boxes): + _kind2count = {history.INT: 1, history.REF: 2, history.FLOAT: 3} + return sorted(boxes, key=lambda box: _kind2count[box.type]) + class BaseTestOptimizeOpt(BaseTest): def invent_fail_descr(self, fail_args): if fail_args is None: return None descr = Storage() - descr.rd_frame_info_list = resume.FrameInfo(None, FakeFrame()) - descr.rd_snapshot = resume.Snapshot(None, fail_args) + descr.rd_frame_info_list = resume.FrameInfo(None, "code", 11) + descr.rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args)) return descr def assert_equal(self, optimized, expected): @@ -273,7 +274,7 @@ i0 = int_add(2, 3) i1 = int_is_true(i0) guard_true(i1) [] - i2 = bool_not(i1) + i2 = int_is_zero(i1) guard_false(i2) [] guard_value(i0, 5) [] jump() @@ -289,7 +290,7 @@ from pypy.jit.metainterp.executor import execute_nonspec from pypy.jit.metainterp.history import BoxInt import random - for opnum in range(rop.INT_ADD, rop.BOOL_NOT+1): + for opnum in range(rop.INT_ADD, rop.SAME_AS+1): try: op = opname[opnum] except KeyError: @@ -309,7 +310,7 @@ jump() """ % (op.lower(), ', '.join(map(str, args))) argboxes = [BoxInt(a) for a in args] - expected_value = execute_nonspec(self.cpu, opnum, + expected_value = execute_nonspec(self.cpu, None, opnum, argboxes).getint() expected = """ [] @@ -410,7 +411,7 @@ self.optimize_loop(ops, 'Not', expected) def test_int_is_true_1(self): - py.test.skip("too bad") + py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -427,6 +428,24 @@ """ self.optimize_loop(ops, 'Not', expected) + def test_int_is_true_is_zero(self): + py.test.skip("XXX implement me") + ops = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + expected = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + self.optimize_loop(ops, 'Not', expected) + def test_ooisnull_oononnull_2(self): ops = """ [p0] @@ -478,13 +497,13 @@ ops = """ [p0] guard_class(p0, ConstClass(node_vtable)) [] - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] jump(p0) """ @@ -499,13 +518,13 @@ ops = """ [p0] setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] guard_nonnull(p0) [] jump(p0) @@ -728,25 +747,25 @@ ops = """ [p0, p1, p2] guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -766,17 +785,17 @@ expected2 = """ [p0, p1, p2] guard_nonnull(p0) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -870,7 +889,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, NULL, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -886,7 +905,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, ConstPtr(myptr), descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -1514,7 +1533,7 @@ """ expected = """ [p1, i2, i3] - guard_true(i3) [p1, i2] + guard_true(i3) [i2, p1] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) @@ -1920,7 +1939,7 @@ ops = """ [p1] guard_class(p1, ConstClass(node_vtable2)) [] - i = ooisnot(ConstPtr(myptr), p1) + i = ptr_ne(ConstPtr(myptr), p1) guard_true(i) [] jump(p1) """ @@ -1936,9 +1955,9 @@ [p0] p1 = getfield_gc(p0, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) guard_true(i1) [] - i2 = ooisnot(p1, p2) + i2 = ptr_ne(p1, p2) guard_false(i2) [] jump(p0) """ @@ -1952,8 +1971,8 @@ def test_remove_duplicate_pure_op(self): ops = """ [p1, p2] - i1 = oois(p1, p2) - i2 = oois(p1, p2) + i1 = ptr_eq(p1, p2) + i2 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -1968,7 +1987,7 @@ """ expected = """ [p1, p2] - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -2024,7 +2043,7 @@ # typically called twice, before and after optimization if self.oparse is None: fdescr.rd_frame_info_list = resume.FrameInfo(None, - FakeFrame()) + "code", 11) fdescr.rd_snapshot = resume.Snapshot(None, fail_args) self.oparse = oparse # @@ -2096,7 +2115,7 @@ for pvar, pfieldname, pfieldvar in pendingfields: box = oparse.getvar(pvar) fielddescr = self.namespace[pfieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, box) @@ -2114,13 +2133,13 @@ if tag[0] in ('virtual', 'vstruct'): fieldname, fieldvalue = fieldtext.split('=') fielddescr = self.namespace[fieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, resolved) elif tag[0] == 'varray': fieldvalue = fieldtext - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETARRAYITEM_GC, tag[1], resolved, ConstInt(index)) @@ -2130,12 +2149,14 @@ index += 1 def check_expanded_fail_descr(self, expectedtext, guard_opnum): + from pypy.jit.metainterp.test.test_resume import ResumeDataFakeReader + from pypy.jit.metainterp.test.test_resume import MyMetaInterp guard_op, = [op for op in self.loop.operations if op.is_guard()] fail_args = guard_op.fail_args fdescr = guard_op.descr assert fdescr.guard_opnum == guard_opnum - reader = resume.ResumeDataReader(fdescr, fail_args, - MyMetaInterp(self.cpu)) + reader = ResumeDataFakeReader(fdescr, fail_args, + MyMetaInterp(self.cpu)) boxes = reader.consume_boxes() self._verify_fail_args(boxes, fdescr.oparse, expectedtext) @@ -2190,7 +2211,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p3, descr=nextdescr) - guard_true(i1, descr=fdescr) [p1, i3] + guard_true(i1, descr=fdescr) [i3, p1] jump(i2, i1, i3, p3) """ expected = """ @@ -2199,15 +2220,14 @@ jump(i2, 1, i3, p3) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3 + self.check_expanded_fail_descr('''i3, p1 where p1 is a node_vtable, valuedescr=1, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p3 ''', rop.GUARD_TRUE) def test_expand_fail_4(self): - for arg in ['p1', 'p1,i2', 'i2,p1', 'p1,p2', 'p2,p1', - 'p1,p2,i2', 'p1,i2,p2', 'p2,p1,i2', - 'p2,i2,p1', 'i2,p1,p2', 'i2,p2,p1']: + for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1', + 'i2,p1,p2', 'i2,p2,p1']: self.make_fail_descr() ops = """ [i1, i2, i3] @@ -2218,7 +2238,7 @@ setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) - guard_true(i1, descr=fdescr) [i4, %s, i3] + guard_true(i1, descr=fdescr) [i4, i3, %s] jump(i1, i2, i3) """ expected = """ @@ -2227,7 +2247,7 @@ jump(1, i2, i3) """ self.optimize_loop(ops % arg, 'Not, Not, Not', expected) - self.check_expanded_fail_descr('''i3, %s, i3 + self.check_expanded_fail_descr('''i3, i3, %s where p1 is a node_vtable, valuedescr=i2, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2''' % arg, rop.GUARD_TRUE) @@ -2242,7 +2262,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p1, descr=nextdescr) # a cycle - guard_true(i1, descr=fdescr) [p1, i3, p2, i4] + guard_true(i1, descr=fdescr) [i3, i4, p1, p2] jump(i2, i1, i3, i4) """ expected = """ @@ -2251,7 +2271,7 @@ jump(i2, 1, i3, i4) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3, p2, i4 + self.check_expanded_fail_descr('''i3, i4, p1, p2 where p1 is a node_vtable, valuedescr=i4, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p1 ''', rop.GUARD_TRUE) @@ -2586,6 +2606,47 @@ ''' self.optimize_loop(ops, 'Not, Not', ops) + def test_call_pure_invalidates_caches(self): + # CALL_PURE should still force the setfield_gc() to occur before it + ops = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call_pure(42, p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + expected = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call(p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + self.optimize_loop(ops, 'Not, Not', expected) + + def test_call_pure_constant_folding(self): + # CALL_PURE is not marked as is_always_pure(), because it is wrong + # to call the function arbitrary many times at arbitrary points in + # time. Check that it is either constant-folded (and replaced by + # the result of the call, recorded as the first arg), or turned into + # a regular CALL. + ops = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i3 = call_pure(42, 123456, 4, 5, 6, descr=plaincalldescr) + i4 = call_pure(43, 123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, i3, i4) + ''' + expected = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i4 = call(123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, 42, i4) + ''' + self.optimize_loop(ops, 'Not, Not, Not', expected) + def test_vref_nonvirtual_nonescape(self): ops = """ [p1] @@ -2616,7 +2677,7 @@ setfield_gc(p2, 5, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p1) """ # XXX we should optimize a bit more the case of a nonvirtual. @@ -2658,7 +2719,7 @@ setfield_gc(p1b, 252, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ self.optimize_loop(ops, 'Not, Not', expected) @@ -2699,7 +2760,7 @@ setfield_gc(p1b, i1, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ # the point of this test is that 'i1' should show up in the fail_args @@ -2770,7 +2831,7 @@ escape(p2) p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [] jump(i1) @@ -2796,7 +2857,7 @@ setfield_gc(p2, 23, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [i1] jump(i1, p1) @@ -2870,31 +2931,31 @@ ''' self.optimize_loop(ops, 'Not', expected) -class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): +##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): - def test_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - expected = """ - [i0] - jump(1) - """ - self.optimize_loop(ops, 'Not', expected) +## def test_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## expected = """ +## [i0] +## jump(1) +## """ +## self.optimize_loop(ops, 'Not', expected) - def test_instanceof_guard_class(self): - ops = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - i1 = instanceof(p0, descr=nodesize) - jump(i1, p0) - """ - expected = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - jump(1, p0) - """ - self.optimize_loop(ops, 'Not, Not', expected) +## def test_instanceof_guard_class(self): +## ops = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## i1 = instanceof(p0, descr=nodesize) +## jump(i1, p0) +## """ +## expected = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## jump(1, p0) +## """ +## self.optimize_loop(ops, 'Not, Not', expected) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_pyjitpl.py Fri Jun 18 20:55:39 2010 @@ -1,49 +1,20 @@ # some unit tests for the bytecode decoding -from pypy.jit.metainterp import pyjitpl, codewriter, resoperation, history +from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp import jitprof -from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.history import History from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.test.test_optimizeopt import equaloplists +from pypy.jit.codewriter.jitcode import JitCode -def make_frame(code): - bytecode = codewriter.JitCode("hello") - bytecode.code = code - bytecode.constants = None - frame = pyjitpl.MIFrame(None, bytecode) - frame.pc = 0 - return frame - - -def test_decode_big_int(): - for code, value in [("\x80\x01", 128), ("\x81\x81\x01", 1 + (1 << 7) + (1 << 14))]: - frame = make_frame(code) - val = frame.load_int() - assert val == value - -def test_decode_bool(): - frame = make_frame("\x00") - assert not frame.load_bool() - - frame = make_frame("\x01") - assert frame.load_bool() - -def test_simple_opimpl_exist(): - rop = resoperation.rop - for opnum, opname in resoperation.opname.items(): - if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE, - rop.FORCE_TOKEN): - continue - if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST: - assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname def test_portal_trace_positions(): - jitcode = codewriter.JitCode("f") - jitcode.code = jitcode.constants = None - portal = codewriter.JitCode("portal") - portal.code = portal.constants = None + jitcode = JitCode("f") + jitcode.setup(None) + portal = JitCode("portal") + portal.setup(None) class FakeStaticData: cpu = None portal_code = portal @@ -95,7 +66,7 @@ c3 = ConstInt(3) boxes = [b1, b2, b1, c3] dup = {} - metainterp.remove_consts_and_duplicates(boxes, 0, 4, dup) + metainterp.remove_consts_and_duplicates(boxes, 4, dup) assert boxes[0] is b1 assert boxes[1] is b2 assert is_another_box_like(boxes[2], b1) @@ -108,12 +79,12 @@ # del metainterp.history.operations[:] b4 = BoxInt(4) - boxes = ["something random", b2, b4, "something else"] - metainterp.remove_consts_and_duplicates(boxes, 1, 3, dup) - assert is_another_box_like(boxes[1], b2) - assert boxes[2] is b4 + boxes = [b2, b4, "something random"] + metainterp.remove_consts_and_duplicates(boxes, 2, dup) + assert is_another_box_like(boxes[0], b2) + assert boxes[1] is b4 assert equaloplists(metainterp.history.operations, [ - ResOperation(rop.SAME_AS, [b2], boxes[1]), + ResOperation(rop.SAME_AS, [b2], boxes[0]), ]) def test_get_name_from_address(): @@ -121,42 +92,7 @@ def __init__(self): pass metainterp_sd = FakeMetaInterpSd() - metainterp_sd.info_from_codewriter(None, None, - [(123, "a"), (456, "b")], - None) + metainterp_sd.setup_list_of_addr2name([(123, 'a'), (456, 'b')]) assert metainterp_sd.get_name_from_address(123) == 'a' assert metainterp_sd.get_name_from_address(456) == 'b' assert metainterp_sd.get_name_from_address(789) == '' - -def test_initialize_state_from_guard_failure(): - from pypy.jit.metainterp.typesystem import llhelper - calls = [] - - class FakeCPU: - ts = llhelper - - def make_boxes_from_latest_values(self, faildescr): - return [BoxInt(0), None, BoxInt(2), None, BoxInt(4)] - - class FakeStaticData: - cpu = FakeCPU() - profiler = jitprof.EmptyProfiler() - - metainterp = pyjitpl.MetaInterp(FakeStaticData()) - - def rebuild_state_after_failure(descr, newboxes): - calls.append(newboxes) - metainterp.rebuild_state_after_failure = rebuild_state_after_failure - - class FakeResumeDescr: - def must_compile(self, *args): - return True - resumedescr = FakeResumeDescr() - metainterp.initialize_state_from_guard_failure(resumedescr) - - inp = metainterp.history.inputargs - assert len(inp) == 3 - assert [box.value for box in inp] == [0, 2, 4] - b0, b2, b4 = inp - assert len(calls) == 1 - assert calls[0] == [b0, None, b2, None, b4] Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_recursive.py Fri Jun 18 20:55:39 2010 @@ -1,7 +1,9 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint +from pypy.rlib.jit import unroll_safe, dont_look_inside +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats @@ -24,6 +26,7 @@ return 1 res = self.meta_interp(main, [20], optimizer=OPTIMIZER_SIMPLE) assert res == main(20) + self.check_history(call=0) def test_simple_recursion_with_exc(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm']) @@ -105,11 +108,11 @@ def can_inline(*args): return True else: - def can_inline(code, i): + def can_inline(i, code): code = hlstr(code) return not JUMP_BACK in code - jitdriver = JitDriver(greens = ['code', 'i'], reds = ['n'], + jitdriver = JitDriver(greens = ['i', 'code'], reds = ['n'], can_inline = can_inline) def interpret(codenum, n, i): @@ -177,13 +180,12 @@ py.test.fail("DID NOT RAISE") def test_guard_failure_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -214,13 +216,12 @@ assert res == 0 def test_guard_failure_and_then_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n', 'flag'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n', 'flag'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -258,13 +259,12 @@ assert res == main(1000) def test_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) class Exc(Exception): @@ -304,13 +304,12 @@ # this passes, if the blackholing shortcut for calls is turned off # it fails, it is very delicate in terms of parameters, # bridge/loop creation order - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -394,9 +393,36 @@ self.check_aborted_count(8) self.check_enter_count_at_most(30) + def test_trace_limit_with_exception_bug(self): + myjitdriver = JitDriver(greens=[], reds=['n']) + @unroll_safe + def do_stuff(n): + while n > 0: + n -= 1 + raise ValueError + def loop(n): + pc = 0 + while n > 80: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + try: + do_stuff(n) + except ValueError: + # the trace limit is checked when we arrive here, and we + # have the exception still in last_exc_value_box at this + # point -- so when we abort because of a trace too long, + # the exception is passed to the blackhole interp and + # incorrectly re-raised from here + pass + n -= 1 + return n + TRACE_LIMIT = 66 + res = self.meta_interp(loop, [100], trace_limit=TRACE_LIMIT) + assert res == 80 + def test_max_failure_args(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -429,7 +455,7 @@ def test_max_failure_args_exc(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -495,12 +521,12 @@ self.check_loops(call_may_force=0, call=0) def test_trace_from_start(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -535,12 +561,12 @@ self.check_history(int_add=1) def test_dont_inline_huge_stuff(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -693,7 +719,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -721,6 +747,60 @@ res = self.meta_interp(main, [0], inline=True) assert res == main(0) + def test_directly_call_assembler_virtualizable_reset_token(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rlib.debug import llinterpcall + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno : str(codeno), + can_inline = lambda codeno : False) + + @dont_look_inside + def check_frame(subframe): + if we_are_translated(): + llinterpcall(lltype.Void, check_ll_frame, subframe) + def check_ll_frame(ll_subframe): + # This is called with the low-level Struct that is the frame. + # Check that the vable_token was correctly reset to zero. + # Note that in order for that test to catch failures, it needs + # three levels of recursion: the vable_token of the subframe + # at the level 2 is set to a non-zero value when doing the + # call to the level 3 only. This used to fail when the test + # is run via pypy.jit.backend.x86.test.test_recursive. + assert ll_subframe.vable_token == 0 + + def main(codeno): + frame = Frame() + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 5: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno < 2: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(codeno + 1, subframe) + check_frame(subframe) + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + res = self.meta_interp(main, [0], inline=True) + assert res == main(0) + def test_directly_call_assembler_virtualizable_force(self): class Thing(object): def __init__(self, val): @@ -729,7 +809,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -770,7 +850,7 @@ assert res == main(0) def test_directly_call_assembler_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'x', 'frame'], virtualizables = ['frame'], can_inline = lambda codeno : False) @@ -816,7 +896,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_resume.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_resume.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_resume.py Fri Jun 18 20:55:39 2010 @@ -3,10 +3,11 @@ from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue from pypy.jit.metainterp.optimizeopt import VStructValue from pypy.jit.metainterp.resume import * -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, ConstAddr +from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.history import ConstPtr, ConstFloat from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin from pypy.jit.metainterp import executor +from pypy.jit.codewriter import heaptracker class Storage: rd_frame_info_list = None @@ -60,12 +61,12 @@ self.resboxes = [] def newframe(self, jitcode): - frame = FakeFrame(jitcode, -1, -1) + frame = FakeFrame(jitcode, -1) self.framestack.append(frame) return frame def execute_and_record(self, opnum, descr, *argboxes): - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) + resbox = executor.execute(self.cpu, None, opnum, descr, *argboxes) self.trace.append((opnum, list(argboxes), resbox, @@ -74,10 +75,75 @@ self.resboxes.append(resbox) return resbox +S = lltype.GcStruct('S') +gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcrefnull = lltype.nullptr(llmemory.GCREF.TO) + +class MyCPU: + class ts: + NULLREF = gcrefnull + CONST_NULL = ConstPtr(gcrefnull) + def __init__(self, values): + self.values = values + def get_latest_value_count(self): + return len(self.values) + def get_latest_value_int(self, index): + return self.values[index] + def get_latest_value_ref(self, index): + return self.values[index] + def get_latest_value_float(self, index): + return self.values[index] + +class MyBlackholeInterp: + def __init__(self, ARGS): + self.written_i = [] + self.written_r = [] + self.written_f = [] + self.ARGS = ARGS + + def get_current_position_info(self): + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + count_i = count_r = count_f = 0 + for index, ARG in enumerate(self.ARGS): + if ARG == lltype.Signed: + callback_i(index, count_i); count_i += 1 + elif ARG == llmemory.GCREF: + callback_r(index, count_r); count_r += 1 + elif ARG == lltype.Float: + callback_f(index, count_f); count_f += 1 + else: + assert 0 + return MyInfo() + + def setarg_i(self, index, value): + assert index == len(self.written_i) + self.written_i.append(value) + + def setarg_r(self, index, value): + assert index == len(self.written_r) + self.written_r.append(value) + + def setarg_f(self, index, value): + assert index == len(self.written_f) + self.written_f.append(value) + +def _next_section(reader, *expected): + bh = MyBlackholeInterp(map(lltype.typeOf, expected)) + reader.consume_one_section(bh) + expected_i = [x for x in expected if lltype.typeOf(x) == lltype.Signed] + expected_r = [x for x in expected if lltype.typeOf(x) == llmemory.GCREF] + expected_f = [x for x in expected if lltype.typeOf(x) == lltype.Float] + assert bh.written_i == expected_i + assert bh.written_r == expected_r + assert bh.written_f == expected_f + def test_simple_read(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] - c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] + #b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] + c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)] storage = Storage() storage.rd_consts = [c1, c2, c3] numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) @@ -88,44 +154,54 @@ tag(0, TAGBOX), tag(1, TAGBOX)]) storage.rd_numb = numb - - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), LLtypeMixin.cpu.ts.CONST_NULL, b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([42, gcref1, -66]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 42, 111, gcrefnull, 42, gcref1) + _next_section(reader, 222, 333) + _next_section(reader, 42, gcref1, -66) + # + metainterp = MyMetaInterp(cpu) + reader = ResumeDataBoxReader(storage, metainterp) + bi, br, bf = [None]*3, [None]*2, [None]*0 + info = MyBlackholeInterp([lltype.Signed, lltype.Signed, + llmemory.GCREF, lltype.Signed, + llmemory.GCREF]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b1s = reader.liveboxes[0] + b2s = reader.liveboxes[1] + assert bi == [b1s, ConstInt(111), b1s] + assert br == [ConstPtr(gcrefnull), b2s] + bi, br, bf = [None]*2, [None]*0, [None]*0 + info = MyBlackholeInterp([lltype.Signed, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + assert bi == [ConstInt(222), ConstInt(333)] + bi, br, bf = [None]*2, [None]*1, [None]*0 + info = MyBlackholeInterp([lltype.Signed, llmemory.GCREF, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b3s = reader.liveboxes[2] + assert bi == [b1s, b3s] + assert br == [b2s] + # def test_simple_read_tagged_ints(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] storage = Storage() storage.rd_consts = [] - numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) - numb = Numbering(numb, [tag(2, TAGINT), tag(3, TAGINT)]) - numb = Numbering(numb, [tag(0, TAGBOX), - tag(1, TAGINT), - tag(0, TAGBOX), - tag(1, TAGBOX)]) + numb = Numbering(None, [tag(100, TAGINT)]) storage.rd_numb = numb - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 100) def test_prepare_virtuals(): class FakeVinfo(object): - def allocate(self, metainterp): + def allocate(self, decoder): return "allocated" - def setfields(self, metainterp, virtual, func): + def setfields(self, decoder, virtual): assert virtual == "allocated" class FakeStorage(object): rd_virtuals = [FakeVinfo(), None] @@ -135,8 +211,8 @@ class FakeMetainterp(object): _already_allocated_resume_virtuals = None cpu = None - reader = ResumeDataReader(FakeStorage(), [], FakeMetainterp()) - assert reader.virtuals == ["allocated", None] + reader = ResumeDataDirectReader(None, FakeStorage()) + assert reader.virtuals == ["allocated", reader.virtual_default] # ____________________________________________________________ @@ -146,11 +222,13 @@ parent_resumedata_snapshot = None parent_resumedata_frame_info_list = None - def __init__(self, code, pc, exc_target, *boxes): + def __init__(self, code, pc, *boxes): self.jitcode = code self.pc = pc - self.exception_target = exc_target - self.env = list(boxes) + self._env = list(boxes) + + def get_list_of_active_boxes(self, flag): + return self._env def setup_resume_at_op(self, pc, exception_target, env): self.__init__(self.jitcode, pc, exception_target, *env) @@ -160,8 +238,7 @@ def __ne__(self, other): return self.__dict__ != other.__dict__ def __repr__(self): - return "" % (self.jitcode, self.pc, - self.exception_target, self.env) + return "" % (self.jitcode, self.pc, self._env) def test_Snapshot_create(): l = ['b0', 'b1'] @@ -176,20 +253,16 @@ def test_FrameInfo_create(): jitcode = "JITCODE" - frame = FakeFrame(jitcode, 1, 2) - fi = FrameInfo(None, frame) + fi = FrameInfo(None, jitcode, 1) assert fi.prev is None assert fi.jitcode is jitcode assert fi.pc == 1 - assert fi.exception_target == 2 jitcode1 = "JITCODE1" - frame1 = FakeFrame(jitcode, 3, 4) - fi1 = FrameInfo(fi, frame1) + fi1 = FrameInfo(fi, jitcode1, 3) assert fi1.prev is fi - assert fi1.jitcode is jitcode + assert fi1.jitcode is jitcode1 assert fi1.pc == 3 - assert fi1.exception_target == 4 def test_Numbering_create(): l = [1, 2] @@ -205,7 +278,7 @@ def test_capture_resumedata(): b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] - fs = [FakeFrame("code0", 0, -1, b1, c1, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2)] storage = Storage() capture_resumedata(fs, None, [], storage) @@ -218,13 +291,12 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) frame_info_list = storage.rd_frame_info_list @@ -235,26 +307,23 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env - assert snapshot.boxes is not fs[2].env + assert snapshot.boxes == fs[2]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is fs[1].parent_resumedata_frame_info_list assert frame_info_list.jitcode == 'code1' snapshot = snapshot.prev assert snapshot.prev is fs[1].parent_resumedata_snapshot - assert snapshot.boxes == fs[1].env - assert snapshot.boxes is not fs[1].env + assert snapshot.boxes == fs[1]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is None assert frame_info_list.jitcode == 'code0' snapshot = snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env - fs[2].env = [b2, b3] + fs[2]._env = [b3, b2] fs[2].pc = 15 vbs = [b1, b2] vrs = [b3] @@ -266,16 +335,11 @@ assert frame_info_list.pc == 15 snapshot = storage.rd_snapshot - assert snapshot.boxes == vbs - assert snapshot.boxes is not vbs - - snapshot = snapshot.prev - assert snapshot.boxes == vrs - assert snapshot.boxes is not vrs + assert snapshot.boxes == vrs + vbs # in the same list snapshot = snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env + assert snapshot.boxes == fs[2]._env class FakeMetaInterpStaticData: @@ -285,12 +349,13 @@ failargs_limit = 100 def test_rebuild_from_resumedata(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -300,21 +365,21 @@ b1t, b2t, b3t = [BoxInt(), BoxPtr(), BoxInt()] newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t) - result = rebuild_from_resumedata(metainterp, newboxes, storage, - False) + result = rebuild_from_resumedata(metainterp, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_with_virtualizable(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxPtr()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, [b4], [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -327,21 +392,22 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, True) assert result == ([b4t], []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -359,9 +425,9 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b2, b3, b4], b1t, b2t, b3t, b4t) @@ -370,7 +436,7 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage2, False) assert result == (None, []) - fs2 = fs2[:-1] + [FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = fs2[:-1] + [FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 @@ -379,6 +445,9 @@ pass fakeoptimizer = FakeOptimizer_VirtualValue() +def ConstAddr(addr, cpu): # compatibility + return ConstInt(heaptracker.adr2int(addr)) + def virtual_value(keybox, value, next): vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu), keybox) @@ -389,17 +458,18 @@ return vv def test_rebuild_from_resumedata_two_guards_w_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -433,9 +503,9 @@ False) b2t = metainterp.resboxes[0] - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b3, b4], b1t, b3t, b4t) @@ -445,17 +515,18 @@ False) b2t = metainterp.resboxes[0] assert len(metainterp.resboxes) == 2 - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards_w_shared_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5, b6 = [BoxPtr(), BoxPtr(), BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, c1, b2, b3)] + fs = [FakeFrame("code0", 0, c1, b2, b3)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -467,7 +538,7 @@ tag(0, TAGCONST)] storage2 = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b4, b2)] + fs = [FakeFrame("code0", 0, b1, b4, b2)] capture_resumedata(fs, None, [], storage2) values[b4] = virtual_value(b4, b6, c4) modifier = ResumeDataVirtualAdder(storage2, memo) @@ -478,9 +549,10 @@ def test_resumedata_top_recursive_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxPtr(), BoxPtr(), BoxInt()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b2)] + fs = [FakeFrame("code0", 0, b1, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -727,16 +799,11 @@ modifier = ResumeDataVirtualAdder(storage, memo) liveboxes = modifier.finish({}) assert storage.rd_snapshot is None - metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, [], metainterp) - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [ConstInt(sys.maxint), ConstInt(1), ConstInt(sys.maxint), - ConstInt(2**16)] - assert metainterp.trace == [] + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, sys.maxint, 2**16, -65) + _next_section(reader, 2, 3) + _next_section(reader, sys.maxint, 1, sys.maxint, 2**16) def test_virtual_adder_memo_const_sharing(): @@ -756,6 +823,46 @@ assert storage2.rd_consts is memo.consts +class ResumeDataFakeReader(ResumeDataBoxReader): + """Another subclass of AbstractResumeDataReader meant for tests.""" + def __init__(self, storage, newboxes, metainterp): + self._init(metainterp.cpu, storage) + self.liveboxes = newboxes + self.metainterp = metainterp + self._prepare(storage) + + def consume_boxes(self): + self.lst = [] + class Whatever: + def __eq__(self, other): + return True + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + for index, tagged in enumerate(self.cur_numb.nums): + box = self.decode_box(tagged, Whatever()) + if box.type == INT: + callback_i(index, index) + elif box.type == REF: + callback_r(index, index) + elif box.type == FLOAT: + callback_f(index, index) + else: + assert 0 + self._prepare_next_section(MyInfo()) + return self.lst + + def write_an_int(self, count_i, box): + assert box.type == INT + self.lst.append(box) + def write_a_ref(self, count_r, box): + assert box.type == REF + self.lst.append(box) + def write_a_float(self, count_f, box): + assert box.type == FLOAT + self.lst.append(box) + + def test_virtual_adder_no_op_renaming(): b1s, b2s, b3s = [BoxInt(1), BoxInt(2), BoxInt(3)] storage = make_storage(b1s, b2s, b3s) @@ -777,7 +884,7 @@ b1t, b3t = [BoxInt(11), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b1_2, b3s], b1t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() assert lst == [b1t, b1t, b3t] lst = reader.consume_boxes() @@ -797,7 +904,7 @@ b2t, b3t = [BoxPtr(demo55o), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() c1t = ConstInt(111) assert lst == [c1t, b2t, b3t] @@ -849,10 +956,10 @@ b5s], b3t, b5t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 2 - b2t = reader._decode_box(modifier._gettagged(b2s)) - b4t = reader._decode_box(modifier._gettagged(b4s)) + b2t = reader.decode_ref(modifier._gettagged(b2s)) + b4t = reader.decode_ref(modifier._gettagged(b4s)) trace = metainterp.trace b2new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu)], @@ -912,9 +1019,9 @@ b4t) # resume metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ (rop.NEW_ARRAY, [ConstInt(2)], b2t, LLtypeMixin.arraydescr), @@ -957,9 +1064,9 @@ # NULL = ConstPtr.value metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ @@ -1004,7 +1111,7 @@ newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert reader.virtuals is None trace = metainterp.trace b2set = (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_send.py Fri Jun 18 20:55:39 2010 @@ -1,7 +1,6 @@ import py from pypy.rlib.jit import JitDriver, hint, purefunction -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -375,7 +374,7 @@ self.check_loop_count(2) def test_behavior_change_after_a_while(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x']) class Base: def __init__(self, value): self.value = value @@ -455,7 +454,7 @@ self.check_tree_loop_count(2) def test_bug1(self): - myjitdriver = JitDriver(greens = [], reds = ['node', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) class Base: pass class A(Base): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_slist.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,4 @@ import py -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE @@ -65,7 +64,7 @@ assert res == 0 def test_getitem(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'lst', 'i']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'lst']) def f(n): lst = [] for i in range(n): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_string.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_string.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_string.py Fri Jun 18 20:55:39 2010 @@ -1,13 +1,13 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class StringTests: def test_eq_residual(self): - jitdriver = JitDriver(greens = [], reds = ['s', 'n', 'i']) + jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's']) global_s = "hello" def f(n, b, s): if b: @@ -23,7 +23,7 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 1}) + self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0}) def test_eq_folded(self): jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i']) @@ -42,10 +42,40 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 0}) + self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0}) + + def test_newstr(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = 'adlfkj' + chr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + + def test_newunicode(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = u'adlfkj' + unichr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 class TestOOtype(StringTests, OOJitMixin): + CALL = "oosend" CALL_PURE = "oosend_pure" class TestLLtype(StringTests, LLJitMixin): + CALL = "call" CALL_PURE = "call_pure" Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tl.py Fri Jun 18 20:55:39 2010 @@ -1,6 +1,6 @@ import py -from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import OPTIMIZER_SIMPLE +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_tlc.py Fri Jun 18 20:55:39 2010 @@ -21,7 +21,7 @@ pool = tlc.ConstantPool() bytecode = tlc.compile(src, pool) interp = self._get_interp(bytecode, pool) - return self.meta_interp(interp, [0, inputarg], view=False) + return self.meta_interp(interp, [0, inputarg]) def test_method(self): code = """ Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtual.py Fri Jun 18 20:55:39 2010 @@ -1,12 +1,12 @@ import py from pypy.rlib.jit import JitDriver, hint from pypy.rlib.objectmodel import compute_unique_id -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.ootypesystem import ootype -from pypy.jit.metainterp import heaptracker +from pypy.jit.codewriter import heaptracker class VirtualTests: def _freeze_(self): @@ -299,10 +299,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) class VirtualMiscTests: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualizable.py Fri Jun 18 20:55:39 2010 @@ -2,14 +2,15 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy +from pypy.jit.codewriter import heaptracker from pypy.rlib.jit import JitDriver, hint, dont_look_inside from pypy.rlib.jit import OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.rarithmetic import intmask from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.rclass import FieldListAccessor from pypy.jit.metainterp.warmspot import get_stats, get_translator -from pypy.jit.metainterp import history, heaptracker +from pypy.jit.metainterp import history from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin def promote_virtualizable(*args): @@ -461,7 +462,7 @@ def test_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -521,7 +522,7 @@ def test_external_pass(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 'z'], + jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'], virtualizables = ['frame']) class BaseFrame(object): @@ -583,6 +584,45 @@ self.check_aborted_count(2) self.check_tree_loop_count(0) + def test_external_read_with_exception(self): + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = ['x', 'y'] + class SomewhereElse: + pass + somewhere_else = SomewhereElse() + + class FooError(Exception): + def __init__(self, value): + self.value = value + + def g(): + result = somewhere_else.top_frame.y # external read + debug_print(lltype.Void, '-+-+-+-+- external read:', result) + raise FooError(result) + + def f(n): + frame = Frame() + frame.x = n + frame.y = 10 + somewhere_else.top_frame = frame + while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) + try: + g() + except FooError, e: + frame.x -= e.value + frame.y += 1 + return frame.x + + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) + assert res == f(123) + self.check_aborted_count(2) + self.check_tree_loop_count(0) + def test_external_write(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -821,7 +861,7 @@ assert res == f(123) def test_external_read_sometimes_recursive(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'rec'], + jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -941,7 +981,7 @@ assert res == f(123) def test_promote_index_in_virtualizable_list(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1084,7 +1124,7 @@ res = self.meta_interp(f, [10]) assert res == 55 - self.check_loops(new_with_vtable=0, oois=1) + self.check_loops(new_with_vtable=0, ptr_eq=1) def test_virtual_child_frame_with_arrays(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], @@ -1196,7 +1236,7 @@ if not self.basic: py.test.skip("purely frontend test") - myjitdriver = JitDriver(greens = [], reds = ['frame', 'fail'], + myjitdriver = JitDriver(greens = [], reds = ['fail', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -1251,7 +1291,7 @@ self.x = x self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) def interp(caller): @@ -1284,15 +1324,15 @@ self.n = n self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['frame'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['frame'], virtualizables=["frame"], get_printable_location=p, can_inline=c) def f(code, frame): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualref.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualref.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_virtualref.py Fri Jun 18 20:55:39 2010 @@ -12,9 +12,9 @@ class VRefTests: - def finish_metainterp_for_interp_operations(self, metainterp): - self.vrefinfo = VirtualRefInfo(metainterp.staticdata.state) - metainterp.staticdata.virtualref_info = self.vrefinfo + def finish_setup_for_interp_operations(self): + self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) + self.cw.setup_vrefinfo(self.vrefinfo) def test_make_vref_simple(self): class X: @@ -81,8 +81,26 @@ JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # - self.metainterp.rebuild_state_after_failure(guard_op.descr, - guard_op.fail_args[:]) + # try reloading from blackhole.py's point of view + from pypy.jit.metainterp.resume import ResumeDataDirectReader + cpu = self.metainterp.cpu + cpu.get_latest_value_count = lambda : len(guard_op.fail_args) + cpu.get_latest_value_int = lambda i:guard_op.fail_args[i].getint() + cpu.get_latest_value_ref = lambda i:guard_op.fail_args[i].getref_base() + cpu.clear_latest_values = lambda count: None + resumereader = ResumeDataDirectReader(cpu, guard_op.descr) + vrefinfo = self.metainterp.staticdata.virtualref_info + lst = [] + vrefinfo.continue_tracing = lambda vref, virtual: \ + lst.append((vref, virtual)) + resumereader.consume_vref_and_vable(vrefinfo, None) + del vrefinfo.continue_tracing + assert len(lst) == 1 + lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), + lst[0][0]) # assert correct type + # + # try reloading from pyjitpl's point of view + self.metainterp.rebuild_state_after_failure(guard_op.descr) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value @@ -424,7 +442,7 @@ self.check_aborted_count(0) def test_recursive_call_1(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: pass @@ -454,7 +472,7 @@ self.check_aborted_count(0) def test_recursive_call_2(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: n = 0 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmspot.py Fri Jun 18 20:55:39 2010 @@ -277,13 +277,13 @@ type_system = 'lltype' class TestOOWarmspot(WarmspotTests, OOJitMixin): - CPUClass = runner.OOtypeCPU + ##CPUClass = runner.OOtypeCPU type_system = 'ootype' class TestWarmspotDirect(object): def setup_class(cls): from pypy.jit.metainterp.typesystem import llhelper - from pypy.jit.metainterp.support import annotate + from pypy.jit.codewriter.support import annotate from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.rpython.lltypesystem import lltype, llmemory @@ -299,7 +299,7 @@ raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally( - [BoxInt(0), BoxInt(1)]) + [0], [], [], [1], [], []) if self.no == 3: exc = lltype.malloc(OBJECT) exc.typeptr = exc_vtable @@ -308,10 +308,15 @@ lltype.cast_opaque_ptr(llmemory.GCREF, exc)) return self.no + class FakeDescr: + def as_vtable_size_descr(self): + return self + class FakeCPU(object): supports_floats = False ts = llhelper translate_support_code = False + stats = "stats" def get_fail_descr_number(self, d): return -1 @@ -320,7 +325,7 @@ pass def nodescr(self, *args, **kwds): - pass + return FakeDescr() fielddescrof = nodescr calldescrof = nodescr sizeof = nodescr @@ -343,6 +348,7 @@ return red rtyper = annotate(f, [0]) + FakeCPU.rtyper = rtyper translator = rtyper.annotator.translator translator.config.translation.gc = 'hybrid' cls.desc = WarmRunnerDesc(translator, CPUClass=FakeCPU) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_warmstate.py Fri Jun 18 20:55:39 2010 @@ -128,8 +128,7 @@ class FakeWarmRunnerDesc: cpu = FakeCPU() red_args_types = ["int", "float"] - class metainterp_sd: - virtualizable_info = None + virtualizable_info = None # state = WarmEnterState(FakeWarmRunnerDesc()) set_future_values = state.make_set_future_values() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_ztranslation.py Fri Jun 18 20:55:39 2010 @@ -5,7 +5,6 @@ from pypy.rlib.jit import PARAMETERS, dont_look_inside from pypy.jit.metainterp.jitprof import Profiler from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.ootypesystem import ootype class TranslationTest: @@ -40,7 +39,7 @@ def can_inline(): return False - jitdriver = JitDriver(greens = [], reds = ['frame', 'total'], + jitdriver = JitDriver(greens = [], reds = ['total', 'frame'], virtualizables = ['frame'], get_jitcell_at=get_jitcell_at, set_jitcell_at=set_jitcell_at, Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/typesystem.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/typesystem.py Fri Jun 18 20:55:39 2010 @@ -4,6 +4,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import r_dict def deref(T): @@ -44,9 +45,9 @@ BASETYPE = llmemory.GCREF BoxRef = history.BoxPtr ConstRef = history.ConstPtr - ConstAddr = history.ConstAddr loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstPtr(history.ConstPtr.value) + NULLREF = history.ConstPtr.value + CONST_NULL = history.ConstPtr(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -71,17 +72,16 @@ def cast_fnptr_to_root(self, fnptr): return llmemory.cast_ptr_to_adr(fnptr) - def cls_of_box(self, cpu, box): + def cls_of_box(self, box): obj = box.getref(lltype.Ptr(rclass.OBJECT)) cls = llmemory.cast_ptr_to_adr(obj.typeptr) - return history.ConstInt(cpu.cast_adr_to_int(cls)) + return history.ConstInt(heaptracker.adr2int(cls)) - def subclassOf(self, cpu, clsbox1, clsbox2): - adr = clsbox2.getaddr(cpu) + def instanceOf(self, instbox, clsbox): + adr = clsbox.getaddr() bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - adr = clsbox1.getaddr(cpu) - real_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - return rclass.ll_issubclass(real_class, bounding_class) + real_instance = instbox.getref(rclass.OBJECTPTR) + return rclass.ll_isinstance(real_instance, bounding_class) def get_exception_box(self, etype): return history.ConstInt(etype) @@ -120,7 +120,7 @@ def cast_vtable_to_hashable(self, cpu, ptr): adr = llmemory.cast_ptr_to_adr(ptr) - return cpu.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) def cast_from_ref(self, TYPE, value): return lltype.cast_opaque_ptr(TYPE, value) @@ -130,8 +130,8 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): - return box.getaddr(cpu) + def getaddr_for_box(self, box): + return box.getaddr() def rd_eq(ref1, ref2): return ref1 == ref2 @@ -151,9 +151,9 @@ BASETYPE = ootype.Object BoxRef = history.BoxObj ConstRef = history.ConstObj - ConstAddr = history.ConstObj loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstObj(history.ConstObj.value) + NULLREF = history.ConstObj.value + CONST_NULL = history.ConstObj(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -233,7 +233,7 @@ return ootype.cast_to_object(value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): + def getaddr_for_box(self, box): return box.getref_base() llhelper = LLTypeHelper() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualizable.py Fri Jun 18 20:55:39 2010 @@ -11,7 +11,7 @@ class VirtualizableInfo: - TOKEN_NONE = 0 + TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 def __init__(self, warmrunnerdesc): @@ -72,6 +72,10 @@ for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] + self.static_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)]) + self.array_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.array_field_descrs)]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem @@ -102,6 +106,52 @@ i = i + 1 assert len(boxes) == i + 1 # + def write_from_resume_data_partial(virtualizable, reader, nums): + # Load values from the reader (see resume.py) described by + # the list of numbers 'nums', and write them in their proper + # place in the 'virtualizable'. This works from the end of + # the list and returns the index in 'nums' of the start of + # the virtualizable data found, allowing the caller to do + # further processing with the start of the list. + i = len(nums) - 1 + assert i >= 0 + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i]) + setarrayitem(lst, j, x) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(FIELDTYPE, nums[i]) + setattr(virtualizable, fieldname, x) + return i + # + def load_list_of_boxes(virtualizable, reader, nums): + # Uses 'virtualizable' only to know the length of the arrays; + # does not write anything into it. The returned list is in + # the format expected of virtualizable_boxes, so it ends in + # the virtualizable itself. + i = len(nums) - 1 + assert i >= 0 + boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])] + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i]) + boxes.append(box) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(FIELDTYPE, nums[i]) + boxes.append(box) + boxes.reverse() + return boxes + # def check_boxes(virtualizable, boxes): # for debugging i = 0 @@ -141,8 +191,14 @@ static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) + unroll_static_fields_rev = unrolling_iterable( + reversed(list(unroll_static_fields))) + unroll_array_fields_rev = unrolling_iterable( + reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes + self.write_from_resume_data_partial = write_from_resume_data_partial + self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length @@ -172,6 +228,9 @@ return self.cpu.ts.cast_to_instance_maybe(self.VTYPEPTR, virtualizable) cast_to_vtype._annspecialcase_ = 'specialize:ll' + def cast_gcref_to_vtype(self, virtualizable): + return lltype.cast_opaque_ptr(self.VTYPEPTR, virtualizable) + def is_vtypeptr(self, TYPE): return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR) @@ -212,12 +271,6 @@ assert virtualizable.vable_token == self.TOKEN_NONE force_now._dont_inline_ = True - def forced_vable(self, virtualizable_boxes): - virtualizable_box = virtualizable_boxes[-1] - virtualizable = self.unwrap_virtualizable_box(virtualizable_box) - self.write_boxes(virtualizable, virtualizable_boxes) - virtualizable.vable_token = self.TOKEN_NONE - # ____________________________________________________________ # # The 'vable_token' field of a virtualizable is either 0, -1, or points Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualref.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualref.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/virtualref.py Fri Jun 18 20:55:39 2010 @@ -1,6 +1,7 @@ from pypy.rpython.rmodel import inputconst, log from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker class VirtualRefInfo: @@ -20,7 +21,8 @@ 'jit_virtual_ref') # build some constants adr = llmemory.cast_ptr_to_adr(self.jit_virtual_ref_vtable) - self.jit_virtual_ref_const_class = history.ConstAddr(adr, self.cpu) + adr = heaptracker.adr2int(adr) + self.jit_virtual_ref_const_class = history.ConstInt(adr) fielddescrof = self.cpu.fielddescrof self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF, 'virtual_token') @@ -60,11 +62,11 @@ # The 'virtual_token' field has the same meaning as the 'vable_token' field # of a virtualizable. It is equal to: - # * -2 (TOKEN_NONE) when tracing, except as described below; + # * -3 (TOKEN_NONE) when tracing, except as described below; # * -1 (TOKEN_TRACING_RESCALL) during tracing when we do a residual call; # * addr in the CPU stack (set by FORCE_TOKEN) when running the assembler; - # * -2 (TOKEN_NONE) after the virtual is forced, if it is forced at all. - TOKEN_NONE = -2 + # * -3 (TOKEN_NONE) after the virtual is forced, if it is forced at all. + TOKEN_NONE = -3 TOKEN_TRACING_RESCALL = -1 def virtual_ref_during_tracing(self, real_object): @@ -104,16 +106,6 @@ # marker "modified during residual call" set. return True - def forced_single_vref(self, gcref, real_object): - if not self.is_virtual_ref(gcref): - return - assert real_object - vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) - assert (vref.virtual_token != self.TOKEN_NONE and - vref.virtual_token != self.TOKEN_TRACING_RESCALL) - vref.virtual_token = self.TOKEN_NONE - vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) - def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmspot.py Fri Jun 18 20:55:39 2010 @@ -16,12 +16,13 @@ from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.unsimplify import call_final_function -from pypy.jit.metainterp import codewriter -from pypy.jit.metainterp import support, history, pyjitpl, gc +from pypy.jit.metainterp import history, pyjitpl, gc from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp -from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler +from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.codewriter import support, codewriter +from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE # ____________________________________________________________ @@ -130,9 +131,6 @@ stats.maybe_view() stats.check_consistency() -class JitException(Exception): - _go_through_llinterp_uncaught_ = True # ugh - class ContinueRunningNormallyBase(JitException): pass @@ -144,47 +142,49 @@ class WarmRunnerDesc(object): def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, - optimizer=None, **kwds): + optimizer=None, ProfilerClass=EmptyProfiler, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! - if policy is None: - policy = JitPolicy() self.set_translator(translator) + self.build_cpu(CPUClass, **kwds) self.find_portal() - self.codewriter = codewriter.CodeWriter(self.rtyper) - graphs = self.codewriter.find_all_graphs(self.portal_graph, - policy, - CPUClass.supports_floats) + self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + if policy is None: + policy = JitPolicy() + policy.set_supports_floats(self.cpu.supports_floats) + graphs = self.codewriter.find_all_graphs(policy) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) - self.build_meta_interp(CPUClass, **kwds) + self.build_meta_interp(ProfilerClass) self.make_args_specification() # from pypy.jit.metainterp.virtualref import VirtualRefInfo - self.metainterp_sd.virtualref_info = VirtualRefInfo(self) + vrefinfo = VirtualRefInfo(self) + self.codewriter.setup_vrefinfo(vrefinfo) if self.jitdriver.virtualizables: from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.metainterp_sd.virtualizable_info = VirtualizableInfo(self) + self.virtualizable_info = VirtualizableInfo(self) + self.codewriter.setup_virtualizable_info(self.virtualizable_info) + else: + self.virtualizable_info = None # self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_function() self.rewrite_jit_merge_point(policy) - - self.codewriter.generate_bytecode(self.metainterp_sd, - self.portal_graph, - self.portal_runner_ptr - ) + + verbose = not self.cpu.translate_support_code + self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jit() self.rewrite_set_param() - self.rewrite_force_virtual() + self.rewrite_force_virtual(vrefinfo) self.add_finish() - self.metainterp_sd.finish_setup(optimizer=optimizer) + self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info if vinfo is not None: vinfo.finish() if self.cpu.translate_support_code: @@ -244,11 +244,10 @@ remove_asserts=True, really_remove_asserts=True) - def build_meta_interp(self, CPUClass, translate_support_code=False, - view="auto", no_stats=False, - ProfilerClass=EmptyProfiler, **kwds): + def build_cpu(self, CPUClass, translate_support_code=False, + no_stats=False, **kwds): assert CPUClass is not None - opt = history.Options(**kwds) + self.opt = history.Options(**kwds) if no_stats: stats = history.NoStats() else: @@ -259,18 +258,18 @@ annhelper = self.annhelper else: annhelper = None - cpu = CPUClass(self.translator.rtyper, self.stats, opt, + cpu = CPUClass(self.translator.rtyper, self.stats, self.opt, translate_support_code, gcdescr=self.gcdescr) self.cpu = cpu - self.metainterp_sd = MetaInterpStaticData(self.portal_graph, # xxx - cpu, - self.stats, opt, + + def build_meta_interp(self, ProfilerClass): + self.metainterp_sd = MetaInterpStaticData(self.cpu, + self.opt, ProfilerClass=ProfilerClass, warmrunnerdesc=self) def make_exception_classes(self): - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(self.PORTAL_FUNCTYPE.ARGS)]) + class DoneWithThisFrameVoid(JitException): def __str__(self): return 'DoneWithThisFrameVoid()' @@ -304,18 +303,19 @@ return 'ExitFrameWithExceptionRef(%s)' % (self.value,) class ContinueRunningNormally(ContinueRunningNormallyBase): - def __init__(self, argboxes): - # accepts boxes as argument, but unpacks them immediately - # before we raise the exception -- the boxes' values will - # be modified in a 'finally' by restore_patched_boxes(). - from pypy.jit.metainterp.warmstate import unwrap - for i, name, ARG in portalfunc_ARGS: - v = unwrap(ARG, argboxes[i]) - setattr(self, name, v) - + def __init__(self, gi, gr, gf, ri, rr, rf): + # the six arguments are: lists of green ints, greens refs, + # green floats, red ints, red refs, and red floats. + self.green_int = gi + self.green_ref = gr + self.green_float = gf + self.red_int = ri + self.red_ref = rr + self.red_float = rf def __str__(self): - return 'ContinueRunningNormally(%s)' % ( - ', '.join(map(str, self.args)),) + return 'ContinueRunningNormally(%s, %s, %s, %s, %s, %s)' % ( + self.green_int, self.green_ref, self.green_float, + self.red_int, self.red_ref, self.red_float) self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt @@ -411,17 +411,10 @@ def make_args_specification(self): graph, block, index = self.jit_merge_point_pos op = block.operations[index] - args = op.args[2:] - ALLARGS = [] - self.green_args_spec = [] - self.red_args_types = [] - for i, v in enumerate(args): - TYPE = v.concretetype - ALLARGS.append(TYPE) - if i < len(self.jitdriver.greens): - self.green_args_spec.append(TYPE) - else: - self.red_args_types.append(history.getkind(TYPE)) + greens_v, reds_v = support.decode_hp_hint_args(op) + ALLARGS = [v.concretetype for v in (greens_v + reds_v)] + self.green_args_spec = [v.concretetype for v in greens_v] + self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] self.num_green_args = len(self.green_args_spec) RESTYPE = graph.getreturnvar().concretetype (self.JIT_ENTER_FUNCTYPE, @@ -443,7 +436,7 @@ continue op = block.operations[index] - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) args_v = greens_v + reds_v vlist = [Constant(jit_enter_fnptr, FUNCPTR)] + args_v @@ -500,13 +493,24 @@ # ____________________________________________________________ # Prepare the portal_runner() helper # + from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) self.portal_ptr = portal_ptr - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)]) - - + # + portalfunc_ARGS = [] + nums = {} + for i, ARG in enumerate(PORTALFUNC.ARGS): + if i < len(self.jitdriver.greens): + color = 'green' + else: + color = 'red' + attrname = '%s_%s' % (color, history.getkind(ARG)) + count = nums.get(attrname, 0) + nums[attrname] = count + 1 + portalfunc_ARGS.append((ARG, attrname, count)) + portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS) + # rtyper = self.translator.rtyper RESULT = PORTALFUNC.RESULT result_kind = history.getkind(RESULT) @@ -520,21 +524,22 @@ portal_ptr)(*args) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -550,8 +555,9 @@ self.PTR_PORTAL_FUNCTYPE.TO, self.PTR_PORTAL_FUNCTYPE.TO.ARGS, self.PTR_PORTAL_FUNCTYPE.TO.RESULT) + self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -565,22 +571,23 @@ fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) return ll_portal_runner(*args) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -597,8 +604,10 @@ if vinfo is not None: self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) + self.cpu.vable_token_descr = vinfo.vable_token_descr else: self.cpu.index_of_virtualizable = -1 + self.cpu.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr @@ -607,7 +616,7 @@ op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v @@ -651,22 +660,8 @@ op.opname = 'direct_call' op.args[:3] = [closures[funcname]] - def rewrite_force_virtual(self): + def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': py.test.skip("rewrite_force_virtual: port it to ootype") all_graphs = self.translator.graphs - vrefinfo = self.metainterp_sd.virtualref_info vrefinfo.replace_force_virtual_with_call(all_graphs) - - -def decode_hp_hint_args(op): - # Returns (list-of-green-vars, list-of-red-vars) without Voids. - assert op.opname == 'jit_marker' - jitdriver = op.args[1].value - numgreens = len(jitdriver.greens) - numreds = len(jitdriver.reds) - greens_v = op.args[2:2+numgreens] - reds_v = op.args[2+numgreens:] - assert len(reds_v) == numreds - return ([v for v in greens_v if v.concretetype is not lltype.Void], - [v for v in reds_v if v.concretetype is not lltype.Void]) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/warmstate.py Fri Jun 18 20:55:39 2010 @@ -11,11 +11,26 @@ from pypy.rlib.jit import DEBUG_PROFILE from pypy.rlib.jit import BaseJitCell from pypy.rlib.debug import debug_start, debug_stop, debug_print -from pypy.jit.metainterp import support, history +from pypy.jit.metainterp import history +from pypy.jit.codewriter import support, heaptracker # ____________________________________________________________ @specialize.arg(0) +def specialize_value(TYPE, x): + """'x' must be a Signed, a GCREF or a Float. + This function casts it to a more specialized type, like Char or Ptr(..). + """ + INPUT = lltype.typeOf(x) + if INPUT is lltype.Signed: + return lltype.cast_primitive(TYPE, x) # XXX missing: Ptr(non-gc) + elif INPUT is lltype.Float: + assert TYPE is lltype.Float + return x + else: + return lltype.cast_opaque_ptr(TYPE, x) + + at specialize.arg(0) def unwrap(TYPE, box): if TYPE is lltype.Void: return None @@ -39,7 +54,7 @@ return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) - value = cpu.cast_adr_to_int(adr) + value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) @@ -180,7 +195,7 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = metainterp_sd.virtualizable_info + vinfo = self.warmrunnerdesc.virtualizable_info num_green_args = self.warmrunnerdesc.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() @@ -401,7 +416,7 @@ warmrunnerdesc = self.warmrunnerdesc cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.metainterp_sd.virtualizable_info + vinfo = warmrunnerdesc.virtualizable_info red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) # def set_future_values(*redargs): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/spli/interpreter.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/spli/interpreter.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/spli/interpreter.py Fri Jun 18 20:55:39 2010 @@ -24,7 +24,7 @@ unrolling_compare_dispatch_table = unrolling_iterable( enumerate(compare_ops)) -jitdriver = JitDriver(greens = ['code', 'instr_index'], +jitdriver = JitDriver(greens = ['instr_index', 'code'], reds = ['frame'], virtualizables = ['frame']) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/tl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/tl.py Fri Jun 18 20:55:39 2010 @@ -56,7 +56,7 @@ def make_interp(supports_call): myjitdriver = JitDriver(greens = ['pc', 'code'], - reds = ['stack', 'inputarg'], + reds = ['inputarg', 'stack'], virtualizables = ['stack']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/targettla.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/targettla.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/targettla.py Fri Jun 18 20:55:39 2010 @@ -28,7 +28,7 @@ def target(driver, args): return entry_point, None -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/tla.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/tla.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/tla/tla.py Fri Jun 18 20:55:39 2010 @@ -71,10 +71,10 @@ # ____________________________________________________________ -def get_printable_location(bytecode, pc): +def get_printable_location(pc, bytecode): return str(pc) -jitdriver = JitDriver(greens=['bytecode', 'pc'], +jitdriver = JitDriver(greens=['pc', 'bytecode'], reds=['self'], virtualizables=['self'], get_printable_location=get_printable_location) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlc.py Fri Jun 18 20:55:39 2010 @@ -226,7 +226,7 @@ def make_interp(supports_call, jitted=True): - myjitdriver = JitDriver(greens = ['code', 'pc'], + myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['frame', 'pool']) def interp(code='', pc=0, inputarg=0, pool=None): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlr.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlr.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tl/tlr.py Fri Jun 18 20:55:39 2010 @@ -12,7 +12,7 @@ NEG_A = 8 class TLRJitDriver(JitDriver): - greens = ['bytecode', 'pc'] + greens = ['pc', 'bytecode'] reds = ['a', 'regs'] tlrjitdriver = TLRJitDriver() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tool/jitoutput.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tool/jitoutput.py Fri Jun 18 20:55:39 2010 @@ -15,14 +15,9 @@ '^Blackhole:\s+([\d.]+)$'), (None, '^TOTAL.*$'), (('ops.total',), '^ops:\s+(\d+)$'), - (('ops.calls',), '^\s+calls:\s+(\d+)$'), - (('ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('recorded_ops.total',), '^recorded ops:\s+(\d+)$'), (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), - (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), - (('blackholed_ops.total',), '^blackholed ops:\s+(\d+)$'), - (('blackholed_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), (('forcings',), '^forcings:\s+(\d+)$'), @@ -36,8 +31,9 @@ class Ops(object): total = 0 + +class RecordedOps(Ops): calls = 0 - pure_calls = 0 class Aborts(object): trace_too_long = 0 @@ -61,8 +57,7 @@ def __init__(self): self.ops = Ops() - self.recorded_ops = Ops() - self.blackholed_ops = Ops() + self.recorded_ops = RecordedOps() self.abort = Aborts() def parse_prof(output): Modified: pypy/branch/x86-64-jit-backend/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/tool/test/test_jitoutput.py Fri Jun 18 20:55:39 2010 @@ -35,14 +35,9 @@ assert info.blackhole_no == 1 assert info.backend_no == 1 assert info.ops.total == 2 - assert info.ops.calls == 0 - assert info.ops.pure_calls == 0 assert info.recorded_ops.total == 2 assert info.recorded_ops.calls == 0 - assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 - assert info.blackholed_ops.total == 0 - assert info.blackholed_ops.pure_calls == 0 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 0 @@ -53,14 +48,9 @@ Blackhole: 1 TOTAL: 0.025532 ops: 2 - calls: 1 - pure calls: 1 recorded ops: 6 calls: 3 - pure calls: 2 guards: 1 -blackholed ops: 5 - pure calls: 3 opt ops: 6 opt guards: 1 forcings: 1 @@ -81,14 +71,9 @@ assert info.backend_no == 1 assert info.backend_time == 0.000525 assert info.ops.total == 2 - assert info.ops.calls == 1 - assert info.ops.pure_calls == 1 assert info.recorded_ops.total == 6 assert info.recorded_ops.calls == 3 - assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 - assert info.blackholed_ops.total == 5 - assert info.blackholed_ops.pure_calls == 3 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 1 Modified: pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_functions.py Fri Jun 18 20:55:39 2010 @@ -210,14 +210,14 @@ result = f(byref(c_int(99))) assert not result.contents == 99 - def test_errors(self): + def test_errors_1(self): f = dll._testfunc_p_p f.restype = c_int class X(Structure): _fields_ = [("y", c_int)] - raises(TypeError, f, X()) #cannot convert parameter + raises(ArgumentError, f, X()) #cannot convert parameter ################################################################ def test_shorts(self): @@ -305,7 +305,7 @@ assert 13577625587 == f(1000000000000, cb) - def test_errors(self): + def test_errors_2(self): raises(AttributeError, getattr, dll, "_xxx_yyy") raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") Modified: pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_unicode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_unicode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/lib/app_test/ctypes_tests/test_unicode.py Fri Jun 18 20:55:39 2010 @@ -90,7 +90,7 @@ assert func(u"abc") == "abc" assert func(u"????") == "" - def test_ascii_replace(self): + def test_ascii_replace_2(self): ctypes.set_conversion_mode("ascii", "replace") assert func("abc") == "abc" assert func(u"abc") == "abc" Modified: pypy/branch/x86-64-jit-backend/pypy/lib/app_test/test_functools.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/lib/app_test/test_functools.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/lib/app_test/test_functools.py Fri Jun 18 20:55:39 2010 @@ -31,7 +31,7 @@ p = self.thetype(map, lambda x: x*10) assert p([1,2,3,4]) == [10, 20, 30, 40] - def test_attributes(self): + def test_attributes_1(self): p = self.thetype(capture, 1, 2, a=10, b=20) # attributes should be readable assert p.func == capture @@ -118,7 +118,7 @@ py.test.raises(ZeroDivisionError, self.thetype(f), 1, 0) py.test.raises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): + def test_attributes_2(self): p = self.thetype(hex) try: del p.__dict__ Modified: pypy/branch/x86-64-jit-backend/pypy/lib/dbm.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/lib/dbm.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/lib/dbm.py Fri Jun 18 20:55:39 2010 @@ -1,4 +1,4 @@ -from ctypes import * +from ctypes import Structure, c_char_p, c_int, c_void_p, CDLL import ctypes.util import os, sys @@ -15,6 +15,11 @@ ('dsize', c_int), ] + def __init__(self, text): + if not isinstance(text, str): + raise TypeError("datum: expected string, not %s" % type(text)) + Structure.__init__(self, text, len(text)) + class dbm(object): def __init__(self, dbmobj): self._aobj = dbmobj @@ -42,9 +47,7 @@ def get(self, key, default=None): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] @@ -65,12 +68,8 @@ def __setitem__(self, key, value): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) - data = datum() - data.dptr = c_char_p(value) - data.dsize = c_int(len(value)) + dat = datum(key) + data = datum(value) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_REPLACE) if getattr(lib, funcs['error'])(self._aobj): getattr(lib, funcs['clearerr'])(self._aobj) @@ -80,15 +79,11 @@ def setdefault(self, key, default=''): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] - data = datum() - data.dptr = c_char_p(default) - data.dsize = c_int(len(default)) + data = datum(default) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_INSERT) if status < 0: getattr(lib, funcs['clearerr'])(self._aobj) @@ -98,9 +93,7 @@ def has_key(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return True @@ -109,9 +102,7 @@ def __delitem__(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) status = getattr(lib, funcs['delete'])(self._aobj, dat) if status < 0: raise KeyError(key) @@ -146,7 +137,7 @@ library = "GNU gdbm" funcs = {} -_init_func('open', [c_char_p, c_int, c_int]) +_init_func('open', (c_char_p, c_int, c_int)) _init_func('close', restype=c_void_p) _init_func('firstkey', restype=datum) _init_func('nextkey', restype=datum) @@ -160,6 +151,9 @@ def open(filename, flag='r', mode=0666): "open a DBM database" + if not isinstance(filename, str): + raise TypeError("expected string") + openflag = 0 try: @@ -177,3 +171,6 @@ if a_db == 0: raise error("Could not open file %s.db" % filename) return dbm(a_db) + +__all__ = ('datum', 'dbm', 'error', 'funcs', 'open', 'library') + Modified: pypy/branch/x86-64-jit-backend/pypy/lib/test2/test_stackless.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/lib/test2/test_stackless.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/lib/test2/test_stackless.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,7 @@ class AppTest_Stackless: def setup_class(cls): - space = gettestobjspace(usemodules=('_stackless',)) + space = gettestobjspace(usemodules=('_stackless','_socket')) cls.space = space # cannot test the unpickle part on top of py.py cls.w_can_unpickle = space.wrap(bool(option.runappdirect)) Modified: pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/functional.py Fri Jun 18 20:55:39 2010 @@ -187,13 +187,15 @@ cont = False args_w = [space.w_None] * num_iterators for i in range(num_iterators): - try: - args_w[i] = space.next(iterators_w[i]) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - else: - cont = True + if iterators_w[i] is not None: + try: + args_w[i] = space.next(iterators_w[i]) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + iterators_w[i] = None + else: + cont = True if cont: w_args = space.newtuple(args_w) if none_func: Modified: pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_classobj.py Fri Jun 18 20:55:39 2010 @@ -477,7 +477,7 @@ assert a is a1 assert a.l == [1, 2] - def test_cmp(self): + def test_cmp_and_coerce(self): class A: def __coerce__(self, other): return (1, 2) Modified: pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/test/test_functional.py Fri Jun 18 20:55:39 2010 @@ -48,16 +48,35 @@ b = [ 2, 3, 4, 5, 6] assert map(None, a, b) == [('1', 2), (2, 3), (3, 4), ('b', 5), (None, 6)] - def test_map_multiply(self): + def test_map_add(self): a = [1, 2, 3, 4] b = [0, 1, 1, 1] - assert map(lambda x, y: x+y, a, b) == [1, 2, 4, 5] + assert map(lambda x, y: x+y, a, b) == [1, 3, 4, 5] - def test_map_multiply(self): + def test_map_first_item(self): a = [1, 2, 3, 4, 5] b = [] assert map(lambda x, y: x, a, b) == a + def test_map_iterables(self): + class A(object): + def __init__(self, n): + self.n = n + def __iter__(self): + return B(self.n) + class B(object): + def __init__(self, n): + self.n = n + def next(self): + self.n -= 1 + if self.n == 0: raise StopIteration + return self.n + result = map(None, A(3), A(8)) + # this also checks that B.next() is not called any more after it + # raised StopIteration once + assert result == [(2, 7), (1, 6), (None, 5), (None, 4), + (None, 3), (None, 2), (None, 1)] + class AppTestZip: def test_one_list(self): assert zip([1,2,3]) == [(1,), (2,), (3,)] Modified: pypy/branch/x86-64-jit-backend/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_codecs/app_codecs.py Fri Jun 18 20:55:39 2010 @@ -39,8 +39,6 @@ # XXX move some of these functions to RPython (like charmap_encode, # charmap_build) to make them faster -import sys - def escape_encode( obj, errors='strict'): """None """ @@ -84,36 +82,36 @@ res = ''.join(res) return res, len(res) -if sys.maxunicode == 65535: - unicode_bytes = 2 -else: - unicode_bytes = 4 - def unicode_internal_encode( obj, errors='strict'): """None """ - if type(obj) == unicode: - p = [] - t = [ord(x) for x in obj] - for i in t: - bytes = [] - for j in xrange(unicode_bytes): - bytes += chr(i%256) - i >>= 8 - if sys.byteorder == "big": - bytes.reverse() - p += bytes - res = ''.join(p) - return res, len(res) + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 else: - res = "You can do better than this" # XXX make this right - return res, len(res) + unicode_bytes = 4 + p = [] + for x in obj: + i = ord(x) + bytes = [] + for j in xrange(unicode_bytes): + bytes += chr(i%256) + i >>= 8 + if sys.byteorder == "big": + bytes.reverse() + p += bytes + res = ''.join(p) + return res, len(res) def unicode_internal_decode( unistr, errors='strict'): - import sys if type(unistr) == unicode: return unistr, len(unistr) else: + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 + else: + unicode_bytes = 4 p = [] i = 0 if sys.byteorder == "big": @@ -541,6 +539,7 @@ hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10, 16)] def hexescape(s, pos, digits, message, errors): + import sys chr = 0 p = [] if (pos+digits>len(s)): @@ -580,6 +579,7 @@ return res, pos def PyUnicode_DecodeUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' @@ -762,6 +762,7 @@ def PyUnicode_DecodeRawUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' Modified: pypy/branch/x86-64-jit-backend/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_codecs/interp_codecs.py Fri Jun 18 20:55:39 2010 @@ -2,6 +2,7 @@ from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder +from pypy.rlib.objectmodel import we_are_translated class CodecState(object): def __init__(self, space): @@ -52,6 +53,9 @@ return replace, newpos return unicode_call_errorhandler + def _freeze_(self): + assert not self.codec_search_path + return False def register_codec(space, w_search_function): """register(search_function) @@ -75,6 +79,8 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ + assert not (space.config.translating and not we_are_translated()), \ + "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() w_result = state.codec_search_cache.get(normalized_encoding, None) @@ -215,11 +221,8 @@ else: encoding = space.str_w(w_encoding) w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) - if space.is_true(w_encoder): - w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) - return space.getitem(w_res, space.wrap(0)) - else: - assert 0, "XXX, what to do here?" + w_res = space.call_function(w_encoder, w_obj, space.wrap(errors)) + return space.getitem(w_res, space.wrap(0)) encode.unwrap_spec = [ObjSpace, W_Root, W_Root, str] def buffer_encode(space, s, errors='strict'): Modified: pypy/branch/x86-64-jit-backend/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_codecs/test/test_codecs.py Fri Jun 18 20:55:39 2010 @@ -84,7 +84,7 @@ assert str(UnicodeTranslateError( u"g\uffffrk", 1, 2, "ouch"))== "can't translate character u'\\uffff' in position 1: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeTranslateError( u"g\U00010000rk", 1, 2, "ouch"))== "can't translate character u'\\U00010000' in position 1: ouch" @@ -107,7 +107,7 @@ assert str(UnicodeEncodeError( "ascii", u"\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\uffff' in position 0: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", u"\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" @@ -229,7 +229,9 @@ def test_unicode_internal_encode(self): import sys - enc = u"a".encode("unicode_internal") + class U(unicode): + pass + enc = U(u"a").encode("unicode_internal") if sys.maxunicode == 65535: # UCS2 build if sys.byteorder == "big": assert enc == "\x00a" @@ -373,7 +375,7 @@ decoded = _codecs.unicode_escape_decode(s)[0] assert decoded == '' - def test_charmap_decode(self): + def test_charmap_decode_1(self): import codecs res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab") assert res == (u"ab\ufffd", 3) @@ -525,7 +527,7 @@ def test_charmap_encode(self): assert 'xxx'.encode('charmap') == 'xxx' - def test_charmap_decode(self): + def test_charmap_decode_2(self): assert 'foo'.decode('charmap') == 'foo' def test_utf7_start_end_in_exception(self): Modified: pypy/branch/x86-64-jit-backend/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_file/test/test_file_extra.py Fri Jun 18 20:55:39 2010 @@ -71,12 +71,6 @@ inputlines = list(self.file) assert inputlines == self.expected_lines - def test_repr(self): - r = repr(self.file) - assert r.find('open file') >= 0 - assert r.find(self.file.name) >= 0 - assert r.find(self.file.mode) >= 0 - def test_isatty(self): assert not self.file.isatty() Modified: pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/array.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/array.py Fri Jun 18 20:55:39 2010 @@ -8,7 +8,7 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror +from pypy.interpreter.error import OperationError from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value Modified: pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/structure.py Fri Jun 18 20:55:39 2010 @@ -9,7 +9,7 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror, operationerrfmt +from pypy.interpreter.error import OperationError, operationerrfmt from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value Modified: pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/_rawffi/test/test__rawffi.py Fri Jun 18 20:55:39 2010 @@ -160,6 +160,17 @@ { return 42; } + + typedef union { + short x; + long y; + } UN; + + UN ret_un_func(UN inp) + { + inp.y = inp.x * 100; + return inp; + } ''')) symbols = """get_char char_check get_raw_pointer @@ -928,6 +939,17 @@ assert a[3] == 'z' assert a[4] == 't' + def test_union(self): + skip("segfaulting") + import _rawffi + longsize = _rawffi.sizeof('l') + S = _rawffi.Structure((longsize, longsize)) + s = S(autofree=False) + lib = _rawffi.CDLL(self.lib_name) + f = lib.ptr('ret_un_func', [(S, 1)], (S, 1)) + ret = f(s) + s.free() + class AppTestAutoFree: def setup_class(cls): space = gettestobjspace(usemodules=('_rawffi', 'struct')) Modified: pypy/branch/x86-64-jit-backend/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/bz2/interp_bz2.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/bz2/interp_bz2.py Fri Jun 18 20:55:39 2010 @@ -172,14 +172,58 @@ space.wrap("wrong sequence of bz2 library commands used")) def _new_buffer_size(current_size): - if current_size > SMALLCHUNK: - # keep doubling until we reach BIGCHUNK - # then keep adding BIGCHUNK - if current_size <= BIGCHUNK: - return current_size + current_size + # keep doubling until we reach BIGCHUNK; then the buffer size is no + # longer increased + if current_size < BIGCHUNK: + return current_size + current_size + return current_size + +# ____________________________________________________________ + +class OutBuffer(object): + """Handler for the output buffer. A bit custom code trying to + encapsulate the logic of setting up the fields of 'bzs' and + allocating raw memory as needed. + """ + def __init__(self, bzs, initial_size=SMALLCHUNK): + # when the constructor is called, allocate a piece of memory + # of length 'piece_size' and make bzs ready to dump there. + self.temp = [] + self.bzs = bzs + self._allocate_chunk(initial_size) + + def _allocate_chunk(self, size): + self.raw_buf, self.gc_buf = rffi.alloc_buffer(size) + self.current_size = size + self.bzs.c_next_out = self.raw_buf + rffi.setintfield(self.bzs, 'c_avail_out', size) + + def _get_chunk(self, chunksize): + assert 0 <= chunksize <= self.current_size + raw_buf = self.raw_buf + gc_buf = self.gc_buf + s = rffi.str_from_buffer(raw_buf, gc_buf, self.current_size, chunksize) + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) + self.current_size = 0 + return s + + def prepare_next_chunk(self): + size = self.current_size + self.temp.append(self._get_chunk(size)) + self._allocate_chunk(_new_buffer_size(size)) + + def make_result_string(self): + count_unoccupied = rffi.getintfield(self.bzs, 'c_avail_out') + s = self._get_chunk(self.current_size - count_unoccupied) + if self.temp: + self.temp.append(s) + return ''.join(self.temp) else: - return current_size + BIGCHUNK - return current_size + SMALLCHUNK + return s + + def free(self): + if self.current_size > 0: + rffi.keep_buffer_alive_until_here(self.raw_buf, self.gc_buf) # ____________________________________________________________ # @@ -488,10 +532,7 @@ raise OperationError(self.space.w_ValueError, self.space.wrap("this object was already flushed")) - out_bufsize = SMALLCHUNK - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', - zero=True) - + out = OutBuffer(self.bzs) in_bufsize = datasize in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw') for i in range(datasize): @@ -501,10 +542,7 @@ self.bzs.c_next_in = in_buf rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize) - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - - temp = [] + while True: bzerror = BZ2_bzCompress(self.bzs, BZ_RUN) if bzerror != BZ_RUN_OK: @@ -513,29 +551,13 @@ if rffi.getintfield(self.bzs, 'c_avail_in') == 0: break elif rffi.getintfield(self.bzs, 'c_avail_out') == 0: - total_out = _bzs_total_out(self.bzs) - data = "".join([out_buf[i] for i in range(total_out)]) - temp.append(data) - - out_bufsize = _new_buffer_size(out_bufsize) - lltype.free(out_buf, flavor='raw') - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, - flavor='raw', zero=True) - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - - if temp: - total_out = _bzs_total_out(self.bzs) - data = "".join([out_buf[i] for i in range(total_out - len(temp[0]))]) - temp.append(data) - return self.space.wrap("".join(temp)) + out.prepare_next_chunk() - total_out = _bzs_total_out(self.bzs) - res = "".join([out_buf[i] for i in range(total_out)]) + res = out.make_result_string() return self.space.wrap(res) finally: lltype.free(in_buf, flavor='raw') - lltype.free(out_buf, flavor='raw') + out.free() compress.unwrap_spec = ['self', 'bufferstr'] @@ -545,18 +567,8 @@ self.space.wrap("this object was already flushed")) self.running = False - out_bufsize = SMALLCHUNK - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', - zero=True) - + out = OutBuffer(self.bzs) try: - - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - - total_out = _bzs_total_out(self.bzs) - - temp = [] while True: bzerror = BZ2_bzCompress(self.bzs, BZ_FINISH) if bzerror == BZ_STREAM_END: @@ -565,29 +577,12 @@ _catch_bz2_error(self.space, bzerror) if rffi.getintfield(self.bzs, 'c_avail_out') == 0: - data = "".join([out_buf[i] for i in range(_bzs_total_out(self.bzs))]) - temp.append(data) - - out_bufsize = _new_buffer_size(out_bufsize) - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, - flavor='raw', zero=True) - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - + out.prepare_next_chunk() - if rffi.getintfield(self.bzs, 'c_avail_out'): - size = _bzs_total_out(self.bzs) - total_out - res = "".join([out_buf[i] for i in range(size)]) - else: - total_out = _bzs_total_out(self.bzs) - res = "".join([out_buf[i] for i in range(total_out)]) - if not temp: - return self.space.wrap(res) - else: - temp.append(res) - return self.space.wrap("".join(temp)) + res = out.make_result_string() + return self.space.wrap(res) finally: - lltype.free(out_buf, flavor='raw') + out.free() flush.unwrap_spec = ['self'] W_BZ2Compressor.typedef = TypeDef("BZ2Compressor", @@ -652,20 +647,11 @@ for i in range(in_bufsize): in_buf[i] = data[i] - out_bufsize = SMALLCHUNK - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', - zero=True) - + out = OutBuffer(self.bzs) try: - self.bzs.c_next_in = in_buf rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize) - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - total_out = _bzs_total_out(self.bzs) - - temp = [] while True: bzerror = BZ2_bzDecompress(self.bzs) if bzerror == BZ_STREAM_END: @@ -680,31 +666,13 @@ if rffi.getintfield(self.bzs, 'c_avail_in') == 0: break elif rffi.getintfield(self.bzs, 'c_avail_out') == 0: - new_total_out = _bzs_total_out(self.bzs) - extra_out = new_total_out - total_out - assert out_bufsize >= extra_out - total_out = new_total_out - data = "".join([out_buf[i] for i in range(extra_out)]) - temp.append(data) - lltype.free(out_buf, flavor='raw') - out_bufsize = _new_buffer_size(out_bufsize) - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw') - self.bzs.c_next_out = out_buf - rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) - - new_total_out = _bzs_total_out(self.bzs) - extra_out = new_total_out - total_out - - if temp: - data = "".join([out_buf[i] for i in range(extra_out)]) - temp.append(data) - return self.space.wrap("".join(temp)) + out.prepare_next_chunk() - res = "".join([out_buf[i] for i in range(extra_out)]) + res = out.make_result_string() return self.space.wrap(res) finally: lltype.free(in_buf, flavor='raw') - lltype.free(out_buf, flavor='raw') + out.free() decompress.unwrap_spec = ['self', 'bufferstr'] @@ -732,10 +700,8 @@ in_bufsize = len(data) # conforming to bz2 manual, this is large enough to fit compressed # data in one shot. We will check it later anyway. - out_bufsize = in_bufsize + (in_bufsize / 100 + 1) + 600 - - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', - zero=True) + out = OutBuffer(bzs, in_bufsize + (in_bufsize / 100 + 1) + 600) + in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw') for i in range(in_bufsize): in_buf[i] = data[i] @@ -743,15 +709,11 @@ try: bzs.c_next_in = in_buf rffi.setintfield(bzs, 'c_avail_in', in_bufsize) - bzs.c_next_out = out_buf - rffi.setintfield(bzs, 'c_avail_out', out_bufsize) bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0) if bzerror != BZ_OK: _catch_bz2_error(space, bzerror) - - total_out = _bzs_total_out(bzs) - temp = [] + while True: bzerror = BZ2_bzCompress(bzs, BZ_FINISH) if bzerror == BZ_STREAM_END: @@ -761,32 +723,15 @@ _catch_bz2_error(space, bzerror) if rffi.getintfield(bzs, 'c_avail_out') == 0: - data = "".join([out_buf[i] for i in range(_bzs_total_out(bzs))]) - temp.append(data) + out.prepare_next_chunk() - lltype.free(out_buf, flavor='raw') - out_bufsize = _new_buffer_size(out_bufsize) - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, - flavor='raw', zero=True) - bzs.c_next_out = out_buf - rffi.setintfield(bzs, 'c_avail_out', out_bufsize) - - if temp: - res = "".join(temp) - - if rffi.getintfield(bzs, 'c_avail_out'): - size = _bzs_total_out(bzs) - total_out - res = "".join([out_buf[i] for i in range(size)]) - else: - total_out = _bzs_total_out(bzs) - res = "".join([out_buf[i] for i in range(total_out)]) - + res = out.make_result_string() BZ2_bzCompressEnd(bzs) return space.wrap(res) finally: lltype.free(bzs, flavor='raw') lltype.free(in_buf, flavor='raw') - lltype.free(out_buf, flavor='raw') + out.free() compress.unwrap_spec = [ObjSpace, 'bufferstr', int] def decompress(space, data): @@ -804,22 +749,15 @@ for i in range(in_bufsize): in_buf[i] = data[i] - out_bufsize = SMALLCHUNK - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', - zero=True) + out = OutBuffer(bzs) try: - - bzs.c_next_in = in_buf rffi.setintfield(bzs, 'c_avail_in', in_bufsize) - bzs.c_next_out = out_buf - rffi.setintfield(bzs, 'c_avail_out', out_bufsize) bzerror = BZ2_bzDecompressInit(bzs, 0, 0) if bzerror != BZ_OK: _catch_bz2_error(space, bzerror) - temp = [] while True: bzerror = BZ2_bzDecompress(bzs) if bzerror == BZ_STREAM_END: @@ -833,29 +771,13 @@ raise OperationError(space.w_ValueError, space.wrap("couldn't find end of stream")) elif rffi.getintfield(bzs, 'c_avail_out') == 0: - total_out = _bzs_total_out(bzs) - data = "".join([out_buf[i] for i in range(total_out)]) - temp.append(data) - - lltype.free(out_buf, flavor='raw') - out_bufsize = _new_buffer_size(out_bufsize) - out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, - flavor='raw', zero=True) - bzs.c_next_out = out_buf - rffi.setintfield(bzs, 'c_avail_out', out_bufsize) - - total_out = _bzs_total_out(bzs) - if temp: - data = "".join([out_buf[i] for i in range(total_out - len(temp[0]))]) - temp.append(data) - res = "".join(temp) - else: - res = "".join([out_buf[i] for i in range(total_out) if out_buf[i] != '\x00']) - + out.prepare_next_chunk() + + res = out.make_result_string() BZ2_bzDecompressEnd(bzs) return space.wrap(res) finally: lltype.free(bzs, flavor='raw') - lltype.free(out_buf, flavor='raw') lltype.free(in_buf, flavor='raw') + out.free() decompress.unwrap_spec = [ObjSpace, 'bufferstr'] Modified: pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/test_bz2_compdecomp.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/test_bz2_compdecomp.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/bz2/test/test_bz2_compdecomp.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,6 @@ from pypy.conftest import gettestobjspace from pypy.module.bz2.test.support import CheckAllocation +from pypy.module.bz2 import interp_bz2 import os, py HUGE_OK = False @@ -27,6 +28,13 @@ mod.DATA = DATA mod.BUGGY_DATA = py.path.local(__file__).dirpath().join('data.bz2').read() mod.decompress = decompress + # + # For tests, patch the value of SMALLCHUNK + mod.OLD_SMALLCHUNK = interp_bz2.SMALLCHUNK + interp_bz2.SMALLCHUNK = 32 + +def teardown_module(mod): + interp_bz2.SMALLCHUNK = mod.OLD_SMALLCHUNK class AppTestBZ2Compressor(CheckAllocation): def setup_class(cls): Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/TODO ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/TODO (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/TODO Fri Jun 18 20:55:39 2010 @@ -15,8 +15,6 @@ - Fix GIL handling (e.g. after releasing the GIL, GC operations might occur in savethreads). - - Export pointers where pointers are expected, i.e. kill the "#define PyExc_OSError &PyExc_OSError" hack. - - refactor management of py_objects_r2w and py_objects_w2r, this can probably be expressed in terms of _PyObject_GC_TRACK macros. Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/__init__.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/__init__.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/__init__.py Fri Jun 18 20:55:39 2010 @@ -64,7 +64,7 @@ import pypy.module.cpyext.sliceobject import pypy.module.cpyext.stubsactive import pypy.module.cpyext.pystate -import pypy.module.cpyext.datetime +import pypy.module.cpyext.cdatetime import pypy.module.cpyext.complexobject import pypy.module.cpyext.weakrefobject import pypy.module.cpyext.funcobject Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/api.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/api.py Fri Jun 18 20:55:39 2010 @@ -11,12 +11,13 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rlib.objectmodel import we_are_translated from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.gensupp import NameManager from pypy.tool.udir import udir from pypy.translator import platform from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError, operationerrfmt -from pypy.interpreter.baseobjspace import W_Root -from pypy.interpreter.gateway import ObjSpace, unwrap_spec +from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.nestedscope import Cell from pypy.interpreter.module import Module from pypy.interpreter.function import StaticMethod @@ -125,14 +126,18 @@ # the error value specifed in the API. # +cpyext_namespace = NameManager('cpyext_') + class ApiFunction: - def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED): + def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, + c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error + self.c_name = c_name # extract the signature from the (CPython-level) code object from pypy.interpreter import pycode @@ -159,6 +164,8 @@ wrapper = make_wrapper(space, self.callable) self._wrapper = wrapper wrapper.relax_sig_check = True + if self.c_name is not None: + wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True): @@ -174,7 +181,7 @@ """ if error is _NOT_SPECIFIED: if restype is PyObject: - error = lltype.nullptr(PyObject.TO) + error = lltype.nullptr(restype.TO) elif restype is lltype.Void: error = CANNOT_FAIL if type(error) is int: @@ -182,11 +189,16 @@ def decorate(func): func_name = func.func_name - api_function = ApiFunction(argtypes, restype, func, error) + if external: + c_name = None + else: + c_name = func_name + api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name) func.api_func = api_function - assert func_name not in FUNCTIONS, "%s already registered" % func_name - assert func_name not in FUNCTIONS_STATIC + if external: + assert func_name not in FUNCTIONS, ( + "%s already registered" % func_name) if error is _NOT_SPECIFIED: raise ValueError("function %s has no return value for exceptions" @@ -224,7 +236,8 @@ elif isinstance(input_arg, W_Root): arg = input_arg else: - arg = from_ref(space, input_arg) + arg = from_ref(space, + rffi.cast(PyObject, input_arg)) else: arg = input_arg newargs += (arg, ) @@ -238,7 +251,7 @@ raise state = space.fromcache(State) state.set_exception(e) - if restype is PyObject: + if is_PyObject(restype): return None else: return api_function.error_value @@ -260,8 +273,6 @@ unwrapper_raise = make_unwrapper(False) if external: FUNCTIONS[func_name] = api_function - else: - FUNCTIONS_STATIC[func_name] = api_function INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests return unwrapper_raise # used in 'normal' RPython code. return decorate @@ -276,7 +287,6 @@ INTERPLEVEL_API = {} FUNCTIONS = {} -FUNCTIONS_STATIC = {} SYMBOLS_C = [ 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse', 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords', @@ -305,6 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'None'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -350,7 +361,9 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr}[ctype] + from pypy.module.cpyext.cdatetime import PyDateTime_CAPI + return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, + "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) @@ -438,6 +451,7 @@ # Make the wrapper for the cases (1) and (2) def make_wrapper(space, callable): + "NOT_RPYTHON" names = callable.api_func.argnames argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, [name.startswith("w_") for name in names]))) @@ -459,9 +473,9 @@ assert len(args) == len(callable.api_func.argtypes) for i, (typ, is_wrapped) in argtypes_enum_ui: arg = args[i] - if typ is PyObject and is_wrapped: + if is_PyObject(typ) and is_wrapped: if arg: - arg_conv = from_ref(space, arg) + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) else: arg_conv = None else: @@ -495,13 +509,14 @@ % (callable.__name__,)) retval = error_value - elif callable.api_func.restype is PyObject: + elif is_PyObject(callable.api_func.restype): if result is None: retval = make_ref(space, None) elif isinstance(result, BorrowPair): retval = result.get_ref(space) elif not rffi._isllptr(result): - retval = make_ref(space, result) + retval = rffi.cast(callable.api_func.restype, + make_ref(space, result)) else: retval = result elif callable.api_func.restype is not lltype.Void: @@ -551,11 +566,27 @@ for func in BOOTSTRAP_FUNCTIONS: func(space) +def c_function_signature(db, func): + restype = db.gettype(func.restype).replace('@', '').strip() + args = [] + for i, argtype in enumerate(func.argtypes): + if argtype is CONST_STRING: + arg = 'const char *@' + elif argtype is CONST_WSTRING: + arg = 'const wchar_t *@' + else: + arg = db.gettype(argtype) + arg = arg.replace('@', 'arg%d' % (i,)).strip() + args.append(arg) + args = ', '.join(args) or "void" + return restype, args + #_____________________________________________________ # Build the bridge DLL, Allow extension DLLs to call # back into Pypy space functions # Do not call this more than once per process def build_bridge(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -567,9 +598,9 @@ # Structure declaration code members = [] structindex = {} - for name, func in FUNCTIONS.iteritems(): - cdecl = db.gettype(func.functype) - members.append(cdecl.replace('@', name) + ';') + for name, func in sorted(FUNCTIONS.iteritems()): + restype, args = c_function_signature(db, func) + members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) struct_declaration_code = """\ @@ -582,8 +613,15 @@ functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] - for name, (type, expr) in GLOBALS.iteritems(): - global_objects.append('%s %s = NULL;' % (type, name.replace("#", ""))) + for name, (typ, expr) in GLOBALS.iteritems(): + if "#" in name: + continue + if typ == 'PyDateTime_CAPI*': + continue + elif name.startswith('PyExc_'): + global_objects.append('%s _%s;' % (typ[:-1], name)) + else: + global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include \n" @@ -603,22 +641,59 @@ # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) - pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # populate static data - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): from pypy.module import cpyext w_obj = eval(expr) - name = name.replace("#", "") + if name.endswith('#'): + name = name[:-1] + isptr = False + else: + isptr = True + if name.startswith('PyExc_'): + isptr = False + INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') - ptr = ctypes.c_void_p.in_dll(bridge, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), - ctypes.c_void_p).value + if isptr: + ptr = ctypes.c_void_p.in_dll(bridge, name) + if typ == 'PyObject*': + value = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + value = w_obj + else: + assert False, "Unknown static pointer: %s %s" % (typ, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), + ctypes.c_void_p).value + elif typ in ('PyObject*', 'PyTypeObject*'): + if name.startswith('PyPyExc_'): + # we already have the pointer + in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) + else: + # we have a structure, get its address + in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) + py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) + from pypy.module.cpyext.pyobject import ( + track_reference, get_typedescr) + w_type = space.type(w_obj) + typedescr = get_typedescr(w_type.instancetypedef) + py_obj.c_ob_refcnt = 1 + py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, + make_ref(space, w_type)) + typedescr.attach(space, py_obj, w_obj) + track_reference(space, py_obj, w_obj) + else: + assert False, "Unknown static object: %s %s" % (typ, name) + + pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # implement structure initialization code for name, func in FUNCTIONS.iteritems(): + if name.startswith('cpyext_'): # XXX hack + continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) @@ -629,23 +704,22 @@ return modulename.new(ext='') def generate_macros(export_symbols, rename=True, do_deref=True): + "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] for name in export_symbols: if name.startswith("PyPy"): renamed_symbols.append(name) continue - if "#" in name: - deref = "*" - if not do_deref and not rename: continue - else: - deref = "" - if not rename: continue + if not rename: + continue name = name.replace("#", "") newname = name.replace('Py', 'PyPy') if not rename: newname = name - pypy_macros.append('#define %s %s%s' % (name, deref, newname)) + pypy_macros.append('#define %s %s' % (name, newname)) + if name.startswith("PyExc_"): + pypy_macros.append('#define _%s _%s' % (name, newname)) renamed_symbols.append(newname) if rename: export_symbols[:] = renamed_symbols @@ -662,11 +736,13 @@ ("SIZEOF_INT", rffi.INT) ]: pypy_macros.append("#define %s %s" % (macro_name, rffi.sizeof(size))) + pypy_macros.append('') pypy_macros_h = udir.join('pypy_macros.h') pypy_macros_h.write('\n'.join(pypy_macros)) -def generate_decls_and_callbacks(db, export_symbols, api_struct=True, globals_are_pointers=True): +def generate_decls_and_callbacks(db, export_symbols, api_struct=True): + "NOT_RPYTHON" # implement function callbacks and generate function decls functions = [] pypy_decls = [] @@ -679,23 +755,15 @@ pypy_decls.append("%s;" % (decl,)) for name, func in sorted(FUNCTIONS.iteritems()): - restype = db.gettype(func.restype).replace('@', '').strip() - args = [] - for i, argtype in enumerate(func.argtypes): - if argtype is CONST_STRING: - arg = 'const char *@' - elif argtype is CONST_WSTRING: - arg = 'const wchar_t *@' - else: - arg = db.gettype(argtype) - arg = arg.replace('@', 'arg%d' % (i,)).strip() - args.append(arg) - args = ', '.join(args) or "void" + restype, args = c_function_signature(db, func) pypy_decls.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args)) if api_struct: callargs = ', '.join('arg%d' % (i,) for i in range(len(func.argtypes))) - body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) + if func.restype is lltype.Void: + body = "{ _pypyAPI.%s(%s); }" % (name, callargs) + else: + body = "{ return _pypyAPI.%s(%s); }" % (name, callargs) functions.append('%s %s(%s)\n%s' % (restype, name, args, body)) for name in VA_TP_LIST: name_no_star = process_va_name(name) @@ -706,12 +774,12 @@ export_symbols.append('pypy_va_get_%s' % (name_no_star,)) for name, (typ, expr) in GLOBALS.iteritems(): - name_clean = name.replace("#", "") - if not globals_are_pointers: + if name.endswith('#'): + name = name.replace("#", "") typ = typ.replace("*", "") - pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name_clean)) - if not globals_are_pointers and "#" not in name: - pypy_decls.append("#define %s (PyObject*)&%s" % (name, name,)) + elif name.startswith('PyExc_'): + typ = 'PyObject*' + pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name)) pypy_decls.append("#ifdef __cplusplus") pypy_decls.append("}") @@ -723,6 +791,7 @@ return functions def build_eci(building_bridge, export_symbols, code): + "NOT_RPYTHON" # Build code and get pointer to the structure kwds = {} export_symbols_eci = export_symbols[:] @@ -733,12 +802,25 @@ if sys.platform == "win32": # '%s' undefined; assuming extern returning int compile_extra.append("/we4013") - else: + elif sys.platform == 'linux2': compile_extra.append("-Werror=implicit-function-declaration") export_symbols_eci.append('pypyAPI') else: kwds["includes"] = ['Python.h'] # this is our Python.h + # Generate definitions for global structures + struct_file = udir.join('pypy_structs.c') + structs = ["#include "] + for name, (typ, expr) in GLOBALS.iteritems(): + if name.endswith('#'): + structs.append('%s %s;' % (typ[:-1], name[:-1])) + elif name.startswith('PyExc_'): + structs.append('extern PyTypeObject _%s;' % (name,)) + structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) + elif typ == 'PyDateTime_CAPI*': + structs.append('%s %s = NULL;' % (typ, name)) + struct_file.write('\n'.join(structs)) + eci = ExternalCompilationInfo( include_dirs=include_dirs, separate_module_files=[source_dir / "varargwrapper.c", @@ -751,6 +833,7 @@ source_dir / "bufferobject.c", source_dir / "object.c", source_dir / "cobject.c", + struct_file, ], separate_module_sources = [code], export_symbols=export_symbols_eci, @@ -761,6 +844,7 @@ def setup_library(space): + "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) @@ -769,7 +853,7 @@ generate_macros(export_symbols, rename=False, do_deref=False) - functions = generate_decls_and_callbacks(db, [], api_struct=False, globals_are_pointers=False) + functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include \n" + "\n".join(functions) eci = build_eci(False, export_symbols, code) @@ -778,20 +862,25 @@ setup_va_functions(eci) # populate static data - for name, (type, expr) in GLOBALS.iteritems(): + for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") + if name.startswith('PyExc_'): + name = '_' + name from pypy.module import cpyext w_obj = eval(expr) - struct_ptr = make_ref(space, w_obj) - struct = rffi.cast(get_structtype_for_ctype(type), struct_ptr)._obj + if typ in ('PyObject*', 'PyTypeObject*'): + struct_ptr = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + continue + else: + assert False, "Unknown static data: %s %s" % (typ, name) + struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) for name, func in FUNCTIONS.iteritems(): deco = entrypoint("cpyext", func.argtypes, name, relax=True) deco(func.get_wrapper(space)) - for name, func in FUNCTIONS_STATIC.iteritems(): - func.get_wrapper(space).c_name = name setup_init_functions(eci) copy_header_files() @@ -802,16 +891,18 @@ state = space.fromcache(State) state.package_context = name try: - from pypy.rlib import libffi + from pypy.rlib import rdynload try: - dll = libffi.CDLL(path, False) - except libffi.DLOpenError, e: + ll_libname = rffi.str2charp(path) + dll = rdynload.dlopen(ll_libname) + lltype.free(ll_libname, flavor='raw') + except rdynload.DLOpenError, e: raise operationerrfmt( space.w_ImportError, "unable to load extension module '%s': %s", path, e.msg) try: - initptr = libffi.dlsym(dll.lib, 'init%s' % (name.split('.')[-1],)) + initptr = rdynload.dlsym(dll, 'init%s' % (name.split('.')[-1],)) except KeyError: raise operationerrfmt( space.w_ImportError, @@ -875,7 +966,7 @@ assert len(args) == len(FT.ARGS) for i, ARG in unrolling_arg_types: arg = args[i] - if ARG is PyObject: + if is_PyObject(ARG): if arg is None: boxed_args += (lltype.nullptr(PyObject.TO),) elif isinstance(arg, W_Root): @@ -898,7 +989,7 @@ finally: state.swap_borrow_container(old_container) - if RESULT_TYPE is PyObject: + if is_PyObject(RESULT_TYPE): if result is None: ret = result elif isinstance(result, W_Root): Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/Python.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/Python.h Fri Jun 18 20:55:39 2010 @@ -15,7 +15,12 @@ #else # define MS_WIN32 1 # define MS_WINDOWS 1 -# include +# ifdef _MSC_VER +# include +# endif +# ifdef __MINGW32__ +# include +# endif # include # define Py_DEPRECATED(VERSION_UNUSED) # ifdef Py_BUILD_CORE @@ -27,16 +32,21 @@ # endif # define Py_LOCAL_INLINE(type) static __inline type __fastcall #endif +#define DL_IMPORT(RTYPE) PyAPI_FUNC(RTYPE) -#define Py_ssize_t long +#include + +#ifndef _WIN32 +typedef intptr_t Py_ssize_t; +#else +typedef long Py_ssize_t; +#endif #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) #define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) #define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE) #define Py_USING_UNICODE -#include - /* Convert a possibly signed character to a nonnegative int */ /* XXX This assumes characters are 8 bits wide */ #ifdef __CHAR_UNSIGNED__ @@ -91,6 +101,7 @@ #include "pycobject.h" #include "bufferobject.h" #include "sliceobject.h" +#include "datetime.h" #include "pystate.h" // XXX This shouldn't be included here @@ -98,6 +109,8 @@ #include +#include "modsupport.inl" + /* Define macros for inline documentation. */ #define PyDoc_VAR(name) static char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/datetime.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/datetime.h Fri Jun 18 20:55:39 2010 @@ -0,0 +1,30 @@ +#ifndef DATETIME_H +#define DATETIME_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; +} PyDateTime_CAPI; + +PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; +#define PyDateTime_IMPORT \ + do { \ + if(PyDateTimeAPI==NULL) \ + PyDateTimeAPI = _PyDateTime_Import(); \ + } while (0) + +typedef struct { + PyObject_HEAD +} PyDateTime_Delta; + +#ifdef __cplusplus +} +#endif +#endif Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/object.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/object.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/object.h Fri Jun 18 20:55:39 2010 @@ -70,6 +70,9 @@ #define Py_NotImplemented (&_Py_NotImplementedStruct) /* Rich comparison opcodes */ +/* + XXX: Also defined in slotdefs.py +*/ #define Py_LT 0 #define Py_LE 1 #define Py_EQ 2 @@ -472,6 +475,9 @@ } \ } while (0) +#define PyObject_TypeCheck(ob, tp) \ + ((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp))) + /* Copied from CPython ----------------------------- */ int PyObject_AsReadBuffer(PyObject *, const void **, Py_ssize_t *); int PyObject_AsWriteBuffer(PyObject *, void **, Py_ssize_t *); Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/stringobject.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/stringobject.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/include/stringobject.h Fri Jun 18 20:55:39 2010 @@ -18,7 +18,7 @@ Py_ssize_t size; } PyStringObject; -PyObject *PyString_FromFormatV(char *format, va_list vargs); +PyObject *PyString_FromFormatV(const char *format, va_list vargs); PyObject *PyString_FromFormat(const char *format, ...); #ifdef __cplusplus Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/listobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/listobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/listobject.py Fri Jun 18 20:55:39 2010 @@ -72,9 +72,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyList_GET_SIZE(space, w_list): """Macro form of PyList_Size() without error checking. - - This macro returned an int. This might require changes in your - code for properly supporting 64-bit systems.""" + """ assert isinstance(w_list, W_ListObject) return len(w_list.wrappeditems) @@ -83,9 +81,7 @@ def PyList_Size(space, ref): """Return the length of the list object in list; this is equivalent to len(list) on a list object. - - This function returned an int. This might require changes in - your code for properly supporting 64-bit systems.""" + """ if not PyList_Check(space, ref): raise OperationError(space.w_TypeError, space.wrap("expected list object")) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/methodobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/methodobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/methodobject.py Fri Jun 18 20:55:39 2010 @@ -1,14 +1,13 @@ -from pypy.interpreter.baseobjspace import Wrappable, W_Root +from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace from pypy.interpreter.typedef import TypeDef, GetSetProperty -from pypy.interpreter.gateway import ObjSpace, W_Root from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.function import BuiltinFunction, Method, StaticMethod from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.pyobject import (PyObject, from_ref, make_ref, make_typedescr, - Py_DecRef) +from pypy.module.cpyext.pyobject import (PyObject, from_ref, make_ref, + make_typedescr, Py_DecRef) from pypy.module.cpyext.api import ( generic_cpy_call, cpython_api, PyObject, cpython_struct, METH_KEYWORDS, METH_O, CONST_STRING, METH_CLASS, METH_STATIC, METH_COEXIST, METH_NOARGS, @@ -235,10 +234,11 @@ def PyDescr_NewMethod(space, w_type, method): return space.wrap(W_PyCMethodObject(space, method, w_type)) -def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, doc, flags, func): +def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, wrapper_func_kwds, + doc, func): # not exactly the API sig return space.wrap(W_PyCWrapperObject(space, pto, method_name, - wrapper_func, doc, flags, func)) + wrapper_func, wrapper_func_kwds, doc, func)) @cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject) def Py_FindMethod(space, table, w_obj, name_ptr): Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/modsupport.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/modsupport.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/modsupport.py Fri Jun 18 20:55:39 2010 @@ -31,9 +31,12 @@ return w_mod +# This is actually the Py_InitModule4 function, +# renamed to refuse modules built against CPython headers. +# The implementation of Py_InitModule4 is in include/modsupport.inl @cpython_api([CONST_STRING, lltype.Ptr(PyMethodDef), CONST_STRING, PyObject, rffi.INT_real], PyObject) -def Py_InitModule4(space, name, methods, doc, w_self, apiver): +def _Py_InitPyPyModule(space, name, methods, doc, w_self, apiver): """ Create a new module object based on a name and table of functions, returning the new module object. If doc is non-NULL, it will be used to define the Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/object.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/object.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/object.py Fri Jun 18 20:55:39 2010 @@ -61,7 +61,7 @@ def PyObject_GC_Del(space, obj): PyObject_Del(space, obj) - at cpython_api([PyObject], lltype.Void) + at cpython_api([rffi.VOIDP_real], lltype.Void) def PyObject_GC_Track(space, op): """Adds the object op to the set of container objects tracked by the collector. The collector can run at unexpected times so objects must be @@ -70,7 +70,7 @@ end of the constructor.""" pass - at cpython_api([rffi.VOIDP], lltype.Void) + at cpython_api([rffi.VOIDP_real], lltype.Void) def PyObject_GC_UnTrack(space, op): """Remove the object op from the set of container objects tracked by the collector. Note that PyObject_GC_Track() can be called again on @@ -284,16 +284,6 @@ w_res = PyObject_RichCompare(space, ref1, ref2, opid) return int(space.is_true(w_res)) - at cpython_api([PyObject, PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyObject_TypeCheck(space, w_obj, w_type): - """Return true if the object o is of type type or a subtype of type. Both - parameters must be non-NULL. - """ - w_obj_type = space.type(w_obj) - assert isinstance(w_type, W_TypeObject) - return int(space.is_w(w_obj_type, w_type) or - space.is_true(space.issubtype(w_obj_type, w_type))) - @cpython_api([PyObject], PyObject) def PyObject_SelfIter(space, ref): """Undocumented function, this is wat CPython does.""" @@ -320,9 +310,14 @@ over setting the attribute in the instance dictionary. Otherwise, the attribute is set in the object's __dict__ (if present). Otherwise, an AttributeError is raised and -1 is returned.""" - from pypy.objspace.descroperation import object_setattr - w_descr = object_setattr(space) - return space.get_and_call_function(w_descr, w_obj, w_name, w_value) + from pypy.objspace.descroperation import object_setattr, object_delattr + if w_value is not None: + w_descr = object_setattr(space) + space.get_and_call_function(w_descr, w_obj, w_name, w_value) + else: + w_descr = object_delattr(space) + space.get_and_call_function(w_descr, w_obj, w_name) + return 0 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) def PyObject_IsInstance(space, w_inst, w_cls): Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/pyobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/pyobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/pyobject.py Fri Jun 18 20:55:39 2010 @@ -2,9 +2,9 @@ from pypy.interpreter.baseobjspace import W_Root, SpaceCache from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import cpython_api, bootstrap_function, \ - PyObject, PyObjectP, ADDR, CANNOT_FAIL, \ - Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr +from pypy.module.cpyext.api import ( + cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR, + CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr) from pypy.module.cpyext.state import State from pypy.objspace.std.typeobject import W_TypeObject from pypy.rlib.objectmodel import specialize, we_are_translated @@ -174,7 +174,7 @@ assert py_obj.c_ob_refcnt == 0 return py_obj else: - lltype.nullptr(PyObject.TO) + return lltype.nullptr(PyObject.TO) def set_lifeline(self, w_obj, py_obj): self.lifeline_dict.set(w_obj, @@ -263,9 +263,9 @@ Allocates a PyObject, and fills its fields with info from the given intepreter object. """ + state = space.fromcache(RefcountState) w_type = space.type(w_obj) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) py_obj = state.get_from_lifeline(w_obj) if py_obj: Py_IncRef(space, py_obj) @@ -274,7 +274,6 @@ typedescr = get_typedescr(w_obj.typedef) py_obj = typedescr.allocate(space, w_type, itemcount=itemcount) if w_type.is_cpytype(): - state = space.fromcache(RefcountState) state.set_lifeline(w_obj, py_obj) typedescr.attach(space, py_obj, w_obj) return py_obj @@ -333,7 +332,7 @@ # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) - if ref_type == ref: + if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sequence.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sequence.py Fri Jun 18 20:55:39 2010 @@ -6,6 +6,12 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.objspace.std import listobject, tupleobject + at cpython_api([PyObject, Py_ssize_t], PyObject) +def PySequence_Repeat(space, w_obj, count): + """Return the result of repeating sequence object o count times, or NULL on + failure. This is the equivalent of the Python expression o * count. + """ + return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PySequence_Check(space, w_obj): @@ -91,6 +97,12 @@ return space.getitem(w_obj, space.wrap(i)) @cpython_api([PyObject], PyObject) +def PySequence_List(space, w_obj): + """Return a list object with the same contents as the arbitrary sequence o. The + returned list is guaranteed to be new.""" + return space.call_function(space.w_list, w_obj) + + at cpython_api([PyObject], PyObject) def PySequence_Tuple(space, w_obj): """Return a tuple object with the same contents as the arbitrary sequence o or NULL on failure. If o is a tuple, a new reference will be returned, Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sliceobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sliceobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/sliceobject.py Fri Jun 18 20:55:39 2010 @@ -56,12 +56,18 @@ the same names. Any of the values may be NULL, in which case the None will be used for the corresponding attribute. Return NULL if the new object could not be allocated.""" + if w_start is None: + w_start = space.w_None + if w_stop is None: + w_stop = space.w_None + if w_step is None: + w_step = space.w_None return W_SliceObject(w_start, w_stop, w_step) - at cpython_api([PyObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, + at cpython_api([PySliceObject, Py_ssize_t, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP, Py_ssize_tP], rffi.INT_real, error=-1) -def PySlice_GetIndicesEx(space, w_slice, length, start_p, stop_p, - step_p, slicelength_p): +def PySlice_GetIndicesEx(space, w_slice, length, start_p, stop_p, step_p, + slicelength_p): """Usable replacement for PySlice_GetIndices(). Retrieve the start, stop, and step indices from the slice object slice assuming a sequence of length length, and store the length of the slice in slicelength. Out Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/slotdefs.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/slotdefs.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/slotdefs.py Fri Jun 18 20:55:39 2010 @@ -1,19 +1,29 @@ import re from pypy.rpython.lltypesystem import rffi, lltype -from pypy.module.cpyext.api import generic_cpy_call, cpython_api, \ - PyObject -from pypy.module.cpyext.typeobjectdefs import unaryfunc, wrapperfunc,\ - ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, lenfunc,\ - ssizeargfunc, ssizessizeargfunc, ssizeobjargproc, iternextfunc,\ - initproc +from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject +from pypy.module.cpyext.typeobjectdefs import ( + unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, + getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc, + ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc, + descrgetfunc, descrsetfunc) from pypy.module.cpyext.pyobject import from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.argument import Arguments from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name +from pypy.rlib.objectmodel import specialize +from pypy.tool.sourcetools import func_renamer +from pypy.rpython.annlowlevel import llhelper + +# XXX: Also defined in object.h +Py_LT = 0 +Py_LE = 1 +Py_EQ = 2 +Py_NE = 3 +Py_GT = 4 +Py_GE = 5 def check_num_args(space, ob, n): @@ -29,7 +39,9 @@ def wrap_init(space, w_self, w_args, func, w_kwargs): func_init = rffi.cast(initproc, func) - generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) + res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) return None def wrap_unaryfunc(space, w_self, w_args, func): @@ -53,6 +65,62 @@ finally: rffi.free_charp(name_ptr) +def wrap_setattr(space, w_self, w_args, func): + func_target = rffi.cast(setattrofunc, func) + check_num_args(space, w_args, 2) + w_name, w_value = space.fixedview(w_args) + # XXX "Carlo Verre hack"? + res = generic_cpy_call(space, func_target, w_self, w_name, w_value) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_delattr(space, w_self, w_args, func): + func_target = rffi.cast(setattrofunc, func) + check_num_args(space, w_args, 1) + w_name, = space.fixedview(w_args) + # XXX "Carlo Verre hack"? + res = generic_cpy_call(space, func_target, w_self, w_name, None) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_descr_get(space, w_self, w_args, func): + func_target = rffi.cast(descrgetfunc, func) + args_w = space.fixedview(w_args) + if len(args_w) == 1: + w_obj, = args_w + w_type = None + elif len(args_w) == 2: + w_obj, w_type = args_w + else: + raise operationerrfmt( + space.w_TypeError, + "expected 1 or 2 arguments, got %d", len(args_w)) + if w_obj is space.w_None: + w_obj = None + if w_type is space.w_None: + w_type = None + if w_obj is None and w_type is None: + raise OperationError( + space.w_TypeError, + space.wrap("__get__(None, None) is invalid")) + return generic_cpy_call(space, func_target, w_self, w_obj, w_type) + +def wrap_descr_set(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 2) + w_obj, w_value = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, w_value) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + +def wrap_descr_delete(space, w_self, w_args, func): + func_target = rffi.cast(descrsetfunc, func) + check_num_args(space, w_args, 1) + w_obj, = space.fixedview(w_args) + res = generic_cpy_call(space, func_target, w_self, w_obj, None) + if rffi.cast(lltype.Signed, res) == -1: + space.fromcache(State).check_and_raise_exception(always=True) + def wrap_call(space, w_self, w_args, func, w_kwds): func_target = rffi.cast(ternaryfunc, func) return generic_cpy_call(space, func_target, w_self, w_args, w_kwds) @@ -105,6 +173,24 @@ raise OperationError(space.w_StopIteration, space.w_None) return w_res +def wrap_hashfunc(space, w_self, w_args, func): + func_target = rffi.cast(hashfunc, func) + check_num_args(space, w_args, 0) + return space.wrap(generic_cpy_call(space, func_target, w_self)) + +def get_richcmp_func(OP_CONST): + def inner(space, w_self, w_args, func): + func_target = rffi.cast(richcmpfunc, func) + check_num_args(space, w_args, 1) + args_w = space.fixedview(w_args) + other_w = args_w[0] + return generic_cpy_call(space, func_target, + w_self, other_w, rffi.cast(rffi.INT_real, OP_CONST)) + return inner + +richcmp_eq = get_richcmp_func(Py_EQ) +richcmp_ne = get_richcmp_func(Py_NE) + @cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False) def slot_tp_new(space, type, w_args, w_kwds): from pypy.module.cpyext.tupleobject import PyTuple_Check @@ -128,36 +214,91 @@ return space.call(w_self, w_args, w_kwds) @cpython_api([PyObject], PyObject, external=False) +def slot_tp_str(space, w_self): + return space.str(w_self) + + at cpython_api([PyObject], PyObject, external=False) def slot_nb_int(space, w_self): return space.int(w_self) +from pypy.rlib.nonconst import NonConstant + +SLOTS = {} + + at specialize.memo() +def get_slot_tp_function(space, typedef, name): + key = (typedef, name) + try: + return SLOTS[key] + except KeyError: + ret = build_slot_tp_function(space, typedef, name) + SLOTS[key] = ret + return ret + +def build_slot_tp_function(space, typedef, name): + w_type = space.gettypeobject(typedef) + + if name == 'tp_setattro': + setattr_fn = w_type.getdictvalue(space, '__setattr__') + delattr_fn = w_type.getdictvalue(space, '__delattr__') + if setattr_fn is None: + return + + @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, + error=-1, external=True) # XXX should not be exported + @func_renamer("cpyext_tp_setattro_%s" % (typedef.name,)) + def slot_tp_setattro(space, w_self, w_name, w_value): + if w_value is not None: + space.call_function(setattr_fn, w_self, w_name, w_value) + else: + space.call_function(delattr_fn, w_self, w_name) + return 0 + api_func = slot_tp_setattro.api_func + else: + return + + return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) + PyWrapperFlag_KEYWORDS = 1 -# adopted from typeobject.c +class TypeSlot: + def __init__(self, method_name, slot_name, function, wrapper1, wrapper2, doc): + self.method_name = method_name + self.slot_name = slot_name + self.slot_names = ("c_" + slot_name).split(".") + self.slot_func = function + self.wrapper_func = wrapper1 + self.wrapper_func_kwds = wrapper2 + self.doc = doc + +# adapted from typeobject.c def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS): - wrapper = globals().get(WRAPPER, Ellipsis) if WRAPPER is None: wrapper = None + else: + wrapper = globals().get(WRAPPER, Ellipsis) + + # irregular interface, because of tp_getattr/tp_getattro confusion if NAME == "__getattr__": wrapper = wrap_getattr + function = globals().get(FUNCTION, None) - slotname = ("c_" + SLOT).split(".") assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func, w_kwds): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = None wrapper2 = wrapper else: if wrapper is Ellipsis: + @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func): raise NotImplementedError("Wrapper for slot " + NAME) - wrapper = func_with_new_name(wrapper, WRAPPER) wrapper1 = wrapper wrapper2 = None - return (NAME, slotname, function, wrapper1, wrapper2, DOC) + return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC): return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0) @@ -410,7 +551,12 @@ for regex, repl in slotdef_replacements: slotdefs_str = re.sub(regex, repl, slotdefs_str) -slotdefs = unrolling_iterable(eval(slotdefs_str)) +slotdefs_for_tp_slots = unrolling_iterable( + [(x.method_name, x.slot_name, x.slot_names, x.slot_func) + for x in eval(slotdefs_str)]) +slotdefs_for_wrappers = unrolling_iterable( + [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) + for x in eval(slotdefs_str)]) if __name__ == "__main__": print slotdefs_str Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/src/stringobject.c ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/src/stringobject.c (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/src/stringobject.c Fri Jun 18 20:55:39 2010 @@ -2,7 +2,7 @@ #include "Python.h" PyObject * -PyString_FromFormatV(char *format, va_list vargs) +PyString_FromFormatV(const char *format, va_list vargs) { va_list count; Py_ssize_t n = 0; Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/state.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/state.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/state.py Fri Jun 18 20:55:39 2010 @@ -1,11 +1,12 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import rffi, lltype -from pypy.lib.identity_dict import identity_dict from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import lltype class State: + datetimeAPI = None # used in tests + def __init__(self, space): self.space = space self.reset() Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stringobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stringobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stringobject.py Fri Jun 18 20:55:39 2010 @@ -180,9 +180,7 @@ the address in *string may differ from its input value. If the reallocation fails, the original string object at *string is deallocated, *string is set to NULL, a memory exception is set, and -1 is returned. - - This function used an int type for newsize. This might - require changes in your code for properly supporting 64-bit systems.""" + """ # XXX always create a new string so far py_str = rffi.cast(PyStringObject, ref[0]) if not py_str.c_buffer: Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stubs.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/stubs.py Fri Jun 18 20:55:39 2010 @@ -23,7 +23,7 @@ _inittab = lltype.Void PyThreadState = lltype.Void PyInterpreterState = lltype.Void -PyOS_sighandler_t = lltype.Void +#PyOS_sighandler_t = lltype.Void Py_UNICODE = lltype.Void PyCompilerFlags = lltype.Void _node = lltype.Void @@ -574,62 +574,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_Check(space, ob): - """Return true if ob is of type PyDateTime_DateType or a subtype of - PyDateTime_DateType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDate_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_Check(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType or a subtype of - PyDateTime_DateTimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DateTimeType. ob must not - be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_Check(space, ob): - """Return true if ob is of type PyDateTime_TimeType or a subtype of - PyDateTime_TimeType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTime_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_TimeType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_Check(space, ob): - """Return true if ob is of type PyDateTime_DeltaType or a subtype of - PyDateTime_DeltaType. ob must not be NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyDelta_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_DeltaType. ob must not be - NULL. - """ - raise NotImplementedError - - at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyTZInfo_Check(space, ob): """Return true if ob is of type PyDateTime_TZInfoType or a subtype of PyDateTime_TZInfoType. ob must not be NULL. @@ -643,108 +587,6 @@ """ raise NotImplementedError - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): - """Return a datetime.date object with the specified year, month and day. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): - """Return a datetime.datetime object with the specified year, month, day, hour, - minute, second and microsecond. - """ - raise NotImplementedError - - at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): - """Return a datetime.timedelta object representing the given number of days, - seconds and microseconds. Normalization is performed so that the resulting - number of microseconds and seconds lie in the ranges documented for - datetime.timedelta objects. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_YEAR(space, o): - """Return the year, as a positive int. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_MONTH(space, o): - """Return the month, as an int from 1 through 12. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_GET_DAY(space, o): - """Return the day, as an int from 1 through 31. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_DATE_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_HOUR(space, o): - """Return the hour, as an int from 0 through 23. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MINUTE(space, o): - """Return the minute, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_SECOND(space, o): - """Return the second, as an int from 0 through 59. - """ - raise NotImplementedError - - at cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) -def PyDateTime_TIME_GET_MICROSECOND(space, o): - """Return the microsecond, as an int from 0 through 999999. - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDateTime_FromTimestamp(space, args): - """Create and return a new datetime.datetime object given an argument tuple - suitable for passing to datetime.datetime.fromtimestamp(). - """ - raise NotImplementedError - - at cpython_api([PyObject], PyObject) -def PyDate_FromTimestamp(space, args): - """Create and return a new datetime.date object given an argument tuple - suitable for passing to datetime.date.fromtimestamp(). - """ - raise NotImplementedError - @cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject) def PyDescr_NewGetSet(space, type, getset): raise NotImplementedError @@ -2363,9 +2205,7 @@ @cpython_api([PyObject], PyObject) def PyObject_Dir(space, o): - """This is equivalent to the Python expression dir(o), returning a (possibly - empty) list of strings appropriate for the object argument, or NULL if there - was an error. If the argument is NULL, this is like the Python dir(), + """This is equivalent to the Python expression dir(o), returning a (possibly empty) list of strings appropriate for the object argument, or NULL if there was an error. If the argument is NULL, this is like the Python dir(), returning the names of the current locals; in this case, if no execution frame is active then NULL is returned but PyErr_Occurred() will return false.""" raise NotImplementedError @@ -2403,15 +2243,6 @@ func.""" raise NotImplementedError - at cpython_api([PyObject, Py_ssize_t], PyObject) -def PySequence_Repeat(space, o, count): - """Return the result of repeating sequence object o count times, or NULL on - failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject], PyObject) def PySequence_InPlaceConcat(space, o1, o2): """Return the concatenation of o1 and o2 on success, and NULL on failure. @@ -2474,12 +2305,6 @@ in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PySequence_List(space, o): - """Return a list object with the same contents as the arbitrary sequence o. The - returned list is guaranteed to be new.""" - raise NotImplementedError - @cpython_api([PyObject], PyObjectP, error=lltype.nullptr(PyObjectP.TO)) def PySequence_Fast_ITEMS(space, o): """Return the underlying array of PyObject pointers. Assumes that o was returned @@ -3142,13 +2967,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsUnicodeEscapeString(space, unicode): - """Encode a Unicode object using Unicode-Escape and return the result as Python - string object. Error handling is "strict". Return NULL if an exception was - raised by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject) def PyUnicode_DecodeRawUnicodeEscape(space, s, size, errors): """Create a Unicode object by decoding size bytes of the Raw-Unicode-Escape @@ -3218,13 +3036,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsASCIIString(space, unicode): - """Encode a Unicode object using ASCII and return the result as Python string - object. Error handling is "strict". Return NULL if an exception was raised - by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject) def PyUnicode_DecodeCharmap(space, s, size, mapping, errors): """Create a Unicode object by decoding size bytes of the encoded string s using Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/foo.c ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/foo.c (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/foo.c Fri Jun 18 20:55:39 2010 @@ -55,7 +55,7 @@ static PyObject * foo_create(fooobject *self) { - return newfooobject(); + return (PyObject*)newfooobject(); } static PyObject * @@ -114,6 +114,25 @@ return kwds; } +static int +foo_setattro(fooobject *self, PyObject *name, PyObject *value) +{ + char *name_str; + if (!PyString_Check(name)) { + PyErr_SetObject(PyExc_AttributeError, name); + return -1; + } + name_str = PyString_AsString(name); + if (strcmp(name_str, "set_foo") == 0) + { + long v = PyInt_AsLong(value); + if (v == -1 && PyErr_Occurred()) + return -1; + self->foo = v; + } + return PyObject_GenericSetAttr((PyObject *)self, name, value); +} + static PyMemberDef foo_members[] = { {"int_member", T_INT, offsetof(fooobject, foo), 0, "A helpful docstring."}, @@ -151,7 +170,7 @@ foo_call, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ - 0, /*tp_setattro*/ + (setattrofunc)foo_setattro, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ @@ -174,8 +193,9 @@ } FuuObject; -void Fuu_init(FuuObject *self, PyObject *args, PyObject *kwargs) { +static int Fuu_init(FuuObject *self, PyObject *args, PyObject *kwargs) { self->val = 42; + return 0; } static PyObject * @@ -242,7 +262,7 @@ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ - Fuu_init, /*tp_init*/ + (initproc) Fuu_init, /*tp_init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_new*/ 0, /*tp_free Low-level free-memory routine */ @@ -398,6 +418,156 @@ }; +static int initerrtype_init(PyObject *self, PyObject *args, PyObject *kwargs) { + PyErr_SetString(PyExc_ValueError, "init raised an error!"); + return -1; +} + + +PyTypeObject InitErrType = { + PyObject_HEAD_INIT(NULL) + 0, + "foo.InitErr", + sizeof(PyObject), + 0, + 0, /*tp_dealloc*/ + 0, /*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*/ + + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + 0, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + initerrtype_init, /*tp_init*/ + 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ + 0, /*tp_new*/ + 0, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + +PyObject * prop_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + if (obj == NULL) + obj = Py_None; + if (type == NULL) + type = Py_None; + + return PyTuple_Pack(3, self, obj, type); +} + +int prop_descr_set(PyObject *self, PyObject *obj, PyObject *value) +{ + int res; + if (value != NULL) { + PyObject *result = PyTuple_Pack(2, self, value); + res = PyObject_SetAttrString(obj, "y", result); + Py_DECREF(result); + } + else { + res = PyObject_SetAttrString(obj, "z", self); + } + return res; +} + + +PyTypeObject SimplePropertyType = { + PyObject_HEAD_INIT(NULL) + 0, + "foo.Property", + sizeof(PyObject), + 0, + 0, /*tp_dealloc*/ + 0, /*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*/ + + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + 0, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + prop_descr_get, /*tp_descr_get*/ + prop_descr_set, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + 0, /*tp_init*/ + 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ + 0, /*tp_new*/ + 0, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + + /* Initialize this module. */ void initfoo(void) @@ -418,6 +588,10 @@ return; if (PyType_Ready(&MetaType) < 0) return; + if (PyType_Ready(&InitErrType) < 0) + return; + if (PyType_Ready(&SimplePropertyType) < 0) + return; m = Py_InitModule("foo", foo_functions); if (m == NULL) return; @@ -432,4 +606,8 @@ return; if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0) return; + if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0) + return; + if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0) + return; } Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cell.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cell.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cell.py Fri Jun 18 20:55:39 2010 @@ -6,7 +6,7 @@ module = self.import_extension('foo', [ ("cell_type", "METH_O", """ - PyDict_SetItemString(args, "cell", &PyCell_Type); + PyDict_SetItemString(args, "cell", (PyObject*)&PyCell_Type); Py_RETURN_NONE; """)]) d = {} Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_cpyext.py Fri Jun 18 20:55:39 2010 @@ -271,6 +271,8 @@ Py_DecRef(self.space, w_obj) state.non_heaptypes_w[:] = [] state.reset_borrowed_references() + from pypy.module.cpyext import cdatetime + cdatetime.datetimeAPI_dealloc(self.space) if self.check_and_print_leaks(): assert False, "Test leaks or loses object(s)." @@ -582,8 +584,8 @@ Py_InitModule("foo", methods); """ body = """ - PyObject* PyPy_Crash1(void); - long PyPy_Crash2(void); + PyAPI_FUNC(PyObject*) PyPy_Crash1(void); + PyAPI_FUNC(long) PyPy_Crash2(void); static PyObject* foo_crash1(PyObject* self, PyObject *args) { return PyPy_Crash1(); Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_datetime.py Fri Jun 18 20:55:39 2010 @@ -1,7 +1,100 @@ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.test.test_api import BaseApiTest +import datetime class TestDatetime(BaseApiTest): + def test_date(self, space, api): + w_date = api.PyDate_FromDate(2010, 06, 03) + assert space.unwrap(space.str(w_date)) == '2010-06-03' + + assert api.PyDate_Check(w_date) + assert api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date)])) == ( + 2010, 06, 03) + def test_time(self, space, api): w_time = api.PyTime_FromTime(23, 15, 40, 123456) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' + + assert api.PyTime_Check(w_time) + assert api.PyTime_CheckExact(w_time) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_TIME_GET_HOUR(w_time), + api.PyDateTime_TIME_GET_MINUTE(w_time), + api.PyDateTime_TIME_GET_SECOND(w_time), + api.PyDateTime_TIME_GET_MICROSECOND(w_time)])) == ( + 23, 15, 40, 123456) + + def test_datetime(self, space, api): + w_date = api.PyDateTime_FromDateAndTime( + 2010, 06, 03, 23, 15, 40, 123456) + assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456' + + assert api.PyDateTime_Check(w_date) + assert api.PyDateTime_CheckExact(w_date) + assert api.PyDate_Check(w_date) + assert not api.PyDate_CheckExact(w_date) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_GET_YEAR(w_date), + api.PyDateTime_GET_MONTH(w_date), + api.PyDateTime_GET_DAY(w_date), + api.PyDateTime_DATE_GET_HOUR(w_date), + api.PyDateTime_DATE_GET_MINUTE(w_date), + api.PyDateTime_DATE_GET_SECOND(w_date), + api.PyDateTime_DATE_GET_MICROSECOND(w_date)])) == ( + 2010, 06, 03, 23, 15, 40, 123456) + + def test_delta(self, space, api): + w_delta = space.appexec( + [space.wrap(3), space.wrap(15)], """(days, seconds): + from datetime import timedelta + return timedelta(days, seconds) + """) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + w_delta = api.PyDelta_FromDSU(10, 20, 30) + assert api.PyDelta_Check(w_delta) + assert api.PyDelta_CheckExact(w_delta) + + assert space.unwrap(space.newtuple([ + api.PyDateTime_DELTA_GET_DAYS(w_delta), + api.PyDateTime_DELTA_GET_SECONDS(w_delta), + api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta)])) == ( + 10, 20, 30) + + def test_fromtimestamp(self, space, api): + w_args = space.wrap((0,)) + w_date = api.PyDate_FromTimestamp(w_args) + date = datetime.date.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) + + w_args = space.wrap((0,)) + w_date = api.PyDateTime_FromTimestamp(w_args) + date = datetime.datetime.fromtimestamp(0) + assert space.unwrap(space.str(w_date)) == str(date) + +class AppTestDatetime(AppTestCpythonExtensionBase): + def test_CAPI(self): + module = self.import_extension('foo', [ + ("get_types", "METH_NOARGS", + """ + PyDateTime_IMPORT; + return PyTuple_Pack(4, + PyDateTimeAPI->DateType, + PyDateTimeAPI->DateTimeType, + PyDateTimeAPI->TimeType, + PyDateTimeAPI->DeltaType); + """), + ]) + import datetime + assert module.get_types() == (datetime.date, + datetime.datetime, + datetime.time, + datetime.timedelta) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_longobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_longobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_longobject.py Fri Jun 18 20:55:39 2010 @@ -76,7 +76,8 @@ """ return PyLong_FromUnsignedLong((unsigned long)-1); """)]) - assert module.from_unsignedlong() == (1<<32) - 1 + import sys + assert module.from_unsignedlong() == 2 * sys.maxint + 1 def test_fromlonglong(self): module = self.import_extension('foo', [ Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_object.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_object.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_object.py Fri Jun 18 20:55:39 2010 @@ -127,17 +127,6 @@ assert api.PyErr_Occurred() is space.w_SystemError api.PyErr_Clear() - def test_TypeCheck(self, space, api): - assert api.PyObject_TypeCheck(space.wrap(1), space.w_int) - assert api.PyObject_TypeCheck(space.wrap(1), api.PyInt_Type) - assert api.PyObject_TypeCheck(space.wrap('foo'), space.w_str) - assert api.PyObject_TypeCheck(space.wrap('foo'), api.PyString_Type) - assert api.PyObject_TypeCheck(space.wrap('foo'), space.w_object) - assert api.PyObject_TypeCheck(space.wrap(1L), api.PyLong_Type) - assert api.PyObject_TypeCheck(space.wrap(True), api.PyBool_Type) - assert api.PyObject_TypeCheck(space.wrap(1.2), api.PyFloat_Type) - assert api.PyObject_TypeCheck(space.w_int, api.PyType_Type) - def test_IsInstance(self, space, api): assert api.PyObject_IsInstance(space.wrap(1), space.w_int) == 1 assert api.PyObject_IsInstance(space.wrap(1), space.w_float) == 0 @@ -203,11 +192,27 @@ space.call_method(w_file, "close") assert (udir / "_test_file").read() == "text" -class AppTestObjectPrint(AppTestCpythonExtensionBase): +class AppTestObject(AppTestCpythonExtensionBase): def setup_class(cls): AppTestCpythonExtensionBase.setup_class.im_func(cls) cls.w_tmpname = cls.space.wrap(str(py.test.ensuretemp("out", dir=0))) + def test_TypeCheck(self): + module = self.import_extension('foo', [ + ("typecheck", "METH_VARARGS", + """ + PyObject *obj = PyTuple_GET_ITEM(args, 0); + PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 1); + return PyBool_FromLong(PyObject_TypeCheck(obj, type)); + """)]) + assert module.typecheck(1, int) + assert module.typecheck('foo', str) + assert module.typecheck('foo', object) + assert module.typecheck(1L, long) + assert module.typecheck(True, bool) + assert module.typecheck(1.2, float) + assert module.typecheck(int, type) + def test_print(self): module = self.import_extension('foo', [ ("dump", "METH_VARARGS", Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sequence.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sequence.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sequence.py Fri Jun 18 20:55:39 2010 @@ -8,7 +8,7 @@ def test_sequence(self, space, api): w_t = space.wrap((1, 2, 3, 4)) assert api.PySequence_Fast(w_t, "message") is w_t - w_l = space.wrap((1, 2, 3, 4)) + w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l assert space.int_w(api.PySequence_Fast_GET_ITEM(w_l, 1)) == 2 @@ -23,6 +23,19 @@ assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + w_seq = api.PySequence_List(w_set) + assert space.type(w_seq) is space.w_list + assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] + + def test_repeat(self, space, api): + def test(seq, count): + w_seq = space.wrap(seq) + w_repeated = api.PySequence_Repeat(w_seq, count) + assert space.eq_w(w_repeated, space.wrap(seq * count)) + + test((1, 2, 3, 4), 3) + test([1, 2, 3, 4], 3) + def test_concat(self, space, api): w_t1 = space.wrap(range(4)) w_t2 = space.wrap(range(4, 8)) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sliceobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sliceobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_sliceobject.py Fri Jun 18 20:55:39 2010 @@ -43,3 +43,12 @@ ]) s = slice(10, 20, 30) assert module.clone(s) == s + + def test_nulls(self): + module = self.import_extension('foo', [ + ("nullslice", "METH_NOARGS", + """ + return PySlice_New(NULL, NULL, NULL); + """), + ]) + assert module.nullslice() == slice(None, None, None) Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_typeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_typeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_typeobject.py Fri Jun 18 20:55:39 2010 @@ -72,6 +72,9 @@ del obj.object_member_ex raises(AttributeError, "del obj.object_member_ex") + obj.set_foo = 32 + assert obj.foo == 32 + def test_typeobject_string_member(self): module = self.import_module(name='foo') obj = module.new() @@ -170,6 +173,61 @@ re._cache.clear() re._cache_repl.clear() + def test_init_error(self): + module = self.import_module("foo") + raises(ValueError, module.InitErrType) + + def test_cmps(self): + module = self.import_module("comparisons") + cmpr = module.CmpType() + assert cmpr == 3 + assert cmpr != 42 + + def test_hash(self): + module = self.import_module("comparisons") + cmpr = module.CmpType() + assert hash(cmpr) == 3 + d = {} + d[cmpr] = 72 + assert d[cmpr] == 72 + assert d[3] == 72 + + def test_descriptor(self): + module = self.import_module("foo") + prop = module.Property() + class C(object): + x = prop + obj = C() + assert obj.x == (prop, obj, C) + assert C.x == (prop, None, C) + + obj.x = 2 + assert obj.y == (prop, 2) + del obj.x + assert obj.z == prop + + def test_tp_dict(self): + foo = self.import_module("foo") + module = self.import_extension('test', [ + ("read_tp_dict", "METH_O", + ''' + PyObject *method; + if (!args->ob_type->tp_dict) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + method = PyDict_GetItemString( + args->ob_type->tp_dict, "copy"); + Py_INCREF(method); + return method; + ''' + ) + ]) + obj = foo.new() + assert module.read_tp_dict(obj) == foo.fooType.copy + + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): w_class = space.appexec([], """(): @@ -206,8 +264,29 @@ w_obj = api._PyType_Lookup(w_type, space.wrap("__invalid")) assert w_obj is None assert api.PyErr_Occurred() is None - + class AppTestSlots(AppTestCpythonExtensionBase): + def test_some_slots(self): + module = self.import_extension('foo', [ + ("test_type", "METH_O", + ''' + if (!args->ob_type->tp_setattro) + { + PyErr_SetString(PyExc_ValueError, "missing tp_setattro"); + return NULL; + } + if (args->ob_type->tp_setattro == + args->ob_type->tp_base->tp_setattro) + { + PyErr_SetString(PyExc_ValueError, "recursive tp_setattro"); + return NULL; + } + Py_RETURN_TRUE; + ''' + ) + ]) + assert module.test_type(type(None)) + def test_nb_int(self): module = self.import_extension('foo', [ ("nb_int", "METH_O", @@ -245,3 +324,21 @@ def __call__(self, *args): return args assert module.tp_call(C(), ('x', 2)) == ('x', 2) + + def test_tp_str(self): + module = self.import_extension('foo', [ + ("tp_str", "METH_O", + ''' + if (!args->ob_type->tp_str) + { + PyErr_SetNone(PyExc_ValueError); + return NULL; + } + return args->ob_type->tp_str(args); + ''' + ) + ]) + class C: + def __str__(self): + return "text" + assert module.tp_str(C()) == "text" Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/test/test_unicodeobject.py Fri Jun 18 20:55:39 2010 @@ -49,7 +49,14 @@ space.newtuple([1, 2, 3]), None, None) self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString, space.wrap(''), None, None) + ascii = rffi.str2charp('ascii') + replace = rffi.str2charp('replace') + encoded = api.PyUnicode_AsEncodedString(space.wrap(u'sp?m'), + ascii, replace) + assert space.unwrap(encoded) == 'sp?m' rffi.free_charp(utf_8) + rffi.free_charp(replace) + rffi.free_charp(ascii) buf = rffi.unicode2wcharp(u"12345") api.PyUnicode_AsWideChar(space.wrap(u'longword'), buf, 5) @@ -143,3 +150,26 @@ rffi.free_wcharp(wbuf) assert space.type(w_str) is space.w_str assert space.str_w(w_str) == "abc?" + + def test_escape(self, space, api): + def test(ustr): + w_ustr = space.wrap(ustr.decode('Unicode-Escape')) + result = api.PyUnicode_AsUnicodeEscapeString(w_ustr) + assert space.eq_w(space.wrap(ustr), result) + + test('\\u674f\\u7f8e') + test('\\u0105\\u0107\\u017c\\u017a') + test('El Ni\\xf1o') + + def test_ascii(self, space, api): + ustr = "abcdef" + w_ustr = space.wrap(ustr.decode("ascii")) + result = api.PyUnicode_AsASCIIString(w_ustr) + + assert space.eq_w(space.wrap(ustr), result) + + w_ustr = space.wrap(u"abcd\xe9f") + result = api.PyUnicode_AsASCIIString(w_ustr) + assert result is None + + Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/typeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/typeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/typeobject.py Fri Jun 18 20:55:39 2010 @@ -25,7 +25,8 @@ from pypy.module.cpyext.typeobjectdefs import ( PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, PyNumberMethods) -from pypy.module.cpyext.slotdefs import slotdefs +from pypy.module.cpyext.slotdefs import ( + slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function) from pypy.interpreter.error import OperationError from pypy.rlib.rstring import rsplit from pypy.rlib.objectmodel import specialize @@ -102,48 +103,60 @@ def update_all_slots(space, w_type, pto): # XXX fill slots in pto - for method_name, slot_name, slot_func, _, _, _ in slotdefs: + + typedef = w_type.instancetypedef + for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: w_descr = w_type.lookup(method_name) if w_descr is None: # XXX special case iternext continue - if slot_func is None: + + slot_func_helper = None + + if slot_func is None and typedef is not None: + get_slot = get_slot_tp_function(space, typedef, slot_name) + if get_slot: + slot_func_helper = get_slot() + elif slot_func: + slot_func_helper = llhelper(slot_func.api_func.functype, + slot_func.api_func.get_wrapper(space)) + + if slot_func_helper is None: if WARN_ABOUT_MISSING_SLOT_FUNCTIONS: os.write(2, method_name + " defined by the type but no slot function defined!\n") continue - slot_func_helper = llhelper(slot_func.api_func.functype, - slot_func.api_func.get_wrapper(space)) + # XXX special case wrapper-functions and use a "specific" slot func - if len(slot_name) == 1: - setattr(pto, slot_name[0], slot_func_helper) + if len(slot_names) == 1: + setattr(pto, slot_names[0], slot_func_helper) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: - if slot_name[0] == 'c_tp_as_number': + if slot_names[0] == 'c_tp_as_number': STRUCT_TYPE = PyNumberMethods else: raise AssertionError( - "Structure not allocated: %s" % (slot_name[0],)) + "Structure not allocated: %s" % (slot_names[0],)) struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) - setattr(pto, slot_name[0], struct) + setattr(pto, slot_names[0], struct) - setattr(struct, slot_name[1], slot_func_helper) + setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): # XXX support PyObject_HashNotImplemented - for method_name, slot_name, _, wrapper_func, wrapper_func_kwds, doc in slotdefs: + for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue - if len(slot_name) == 1: - func = getattr(pto, slot_name[0]) + if len(slot_names) == 1: + func = getattr(pto, slot_names[0]) else: - assert len(slot_name) == 2 - struct = getattr(pto, slot_name[0]) + assert len(slot_names) == 2 + struct = getattr(pto, slot_names[0]) if not struct: continue - func = getattr(struct, slot_name[1]) + func = getattr(struct, slot_names[1]) func_voidp = rffi.cast(rffi.VOIDP_real, func) if not func: continue @@ -363,12 +376,13 @@ @cpython_api([PyObject], lltype.Void, external=False) def type_dealloc(space, obj): + from pypy.module.cpyext.object import PyObject_dealloc obj_pto = rffi.cast(PyTypeObjectPtr, obj) - type_pto = obj.c_ob_type base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base) Py_DecRef(space, obj_pto.c_tp_bases) Py_DecRef(space, obj_pto.c_tp_mro) Py_DecRef(space, obj_pto.c_tp_cache) # let's do it like cpython + Py_DecRef(space, obj_pto.c_tp_dict) if obj_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: if obj_pto.c_tp_as_buffer: lltype.free(obj_pto.c_tp_as_buffer, flavor='raw') @@ -376,11 +390,7 @@ lltype.free(obj_pto.c_tp_as_number, flavor='raw') Py_DecRef(space, base_pyo) rffi.free_charp(obj_pto.c_tp_name) - obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto) - generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp) - if type_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: - pto = rffi.cast(PyObject, type_pto) - Py_DecRef(space, pto) + PyObject_dealloc(space, obj) def type_attach(space, py_obj, w_type): @@ -494,6 +504,8 @@ # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free + if not pto.c_tp_setattro: + pto.c_tp_setattro = base.c_tp_setattro finally: Py_DecRef(space, base_pyo) @@ -532,8 +544,6 @@ """ Sets up tp_bases, necessary before creating the interpreter type. """ - pto.c_tp_dict = lltype.nullptr(PyObject.TO) # not supported - base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: @@ -558,6 +568,16 @@ for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): inherit_slots(space, pto, w_base) + if not pto.c_tp_setattro: + from pypy.module.cpyext.object import PyObject_GenericSetAttr + pto.c_tp_setattro = llhelper( + PyObject_GenericSetAttr.api_func.functype, + PyObject_GenericSetAttr.api_func.get_wrapper(space)) + + if w_obj.is_cpytype(): + Py_DecRef(space, pto.c_tp_dict) + pto.c_tp_dict = make_ref(space, w_obj.getdict()) + @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL) def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. Modified: pypy/branch/x86-64-jit-backend/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/cpyext/unicodeobject.py Fri Jun 18 20:55:39 2010 @@ -105,10 +105,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyUnicode_GET_SIZE(space, w_obj): """Return the size of the object. o has to be a PyUnicodeObject (not - checked). - - This function returned an int type. This might require changes - in your code for properly supporting 64-bit systems.""" + checked).""" assert isinstance(w_obj, unicodeobject.W_UnicodeObject) return space.int_w(space.len(w_obj)) @@ -190,7 +187,7 @@ return 0 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject) -def PyUnicode_AsEncodedString(space, w_unicode, encoding, errors): +def PyUnicode_AsEncodedString(space, w_unicode, llencoding, llerrors): """Encode a Unicode object and return the result as Python string object. encoding and errors have the same meaning as the parameters of the same name in the Unicode encode() method. The codec to be used is looked up using @@ -199,12 +196,22 @@ if not PyUnicode_Check(space, w_unicode): PyErr_BadArgument(space) - w_encoding = w_errors = None - if encoding: - w_encoding = rffi.charp2str(encoding) - if errors: - w_errors = rffi.charp2str(encoding) - return unicodetype.encode_object(space, w_unicode, w_encoding, w_errors) + encoding = errors = None + if llencoding: + encoding = rffi.charp2str(llencoding) + if llerrors: + errors = rffi.charp2str(llerrors) + return unicodetype.encode_object(space, w_unicode, encoding, errors) + + at cpython_api([PyObject], PyObject) +def PyUnicode_AsUnicodeEscapeString(space, w_unicode): + """Encode a Unicode object using Unicode-Escape and return the result as Python + string object. Error handling is "strict". Return NULL if an exception was + raised by the codec.""" + if not PyUnicode_Check(space, w_unicode): + PyErr_BadArgument(space) + + return unicodetype.encode_object(space, w_unicode, 'unicode-escape', 'strict') @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject) def PyUnicode_FromUnicode(space, wchar_p, length): @@ -300,6 +307,19 @@ w_errors = space.w_None return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors) + at cpython_api([PyObject], PyObject) +def PyUnicode_AsASCIIString(space, w_unicode): + """Encode a Unicode object using ASCII and return the result as Python string + object. Error handling is "strict". Return NULL if an exception was raised + by the codec.""" + try: + return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors? + except OperationError, e: + if e.match(space, space.w_UnicodeEncodeError): + return None + else: + raise + if sys.platform == 'win32': @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject) def PyUnicode_EncodeMBCS(space, wchar_p, length, errors): Modified: pypy/branch/x86-64-jit-backend/pypy/module/imp/importing.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/imp/importing.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/imp/importing.py Fri Jun 18 20:55:39 2010 @@ -145,7 +145,7 @@ msg = "Attempted relative import in non-package" raise OperationError(space.w_ValueError, w(msg)) w_mod = absolute_import_try(space, modulename, 0, fromlist_w) - if w_mod is None and not space.is_w(w_mod, space.w_None): + if w_mod is None or space.is_w(w_mod, space.w_None): w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0) if rel_modulename is not None: space.setitem(space.sys.get('modules'), w(rel_modulename), space.w_None) @@ -178,13 +178,11 @@ else: level = 0 first = None - while last_dot != -1: - assert last_dot >= 0 # bah + while last_dot >= 0: last_dot = modulename.find('.', last_dot + 1) - if last_dot == -1: + if last_dot < 0: w_mod = check_sys_modules_w(space, modulename) else: - assert last_dot >= 0 w_mod = check_sys_modules_w(space, modulename[:last_dot]) if w_mod is None or space.is_w(w_mod, space.w_None): return None Modified: pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_app.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_app.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_app.py Fri Jun 18 20:55:39 2010 @@ -71,7 +71,8 @@ import test_imp_extra_AUTO1 assert mod is test_imp_extra_AUTO1 - def test_load_module_pyc(self): + def test_load_module_pyc_1(self): + import os fn = self._pyc_file() try: descr = ('.pyc', 'rb', self.imp.PY_COMPILED) @@ -91,7 +92,7 @@ import test_imp_extra_AUTO3 assert mod is test_imp_extra_AUTO3 - def test_load_module_pyc(self): + def test_load_module_pyc_2(self): import os fn = self._pyc_file() try: Modified: pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_import.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_import.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/imp/test/test_import.py Fri Jun 18 20:55:39 2010 @@ -457,6 +457,16 @@ def test_reload_infinite(self): import infinite_reload + def test_explicitly_missing(self): + import sys + sys.modules['foobarbazmod'] = None + try: + import foobarbazmod + assert False, "should have failed, got instead %r" % ( + foobarbazmod,) + except ImportError: + pass + def _getlong(data): x = marshal.dumps(data) return x[-4:] Modified: pypy/branch/x86-64-jit-backend/pypy/module/itertools/test/test_itertools.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/itertools/test/test_itertools.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/itertools/test/test_itertools.py Fri Jun 18 20:55:39 2010 @@ -130,7 +130,7 @@ raises(StopIteration, it.next) - def test_takewhile_wrongargs(self): + def test_dropwhile_wrongargs(self): import itertools it = itertools.dropwhile(None, [1]) Modified: pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/policy.py Fri Jun 18 20:55:39 2010 @@ -1,4 +1,4 @@ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy class PyPyJitPolicy(JitPolicy): Modified: pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/test/test_pypy_c.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/test/test_pypy_c.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/pypyjit/test/test_pypy_c.py Fri Jun 18 20:55:39 2010 @@ -222,7 +222,7 @@ while i < n+OFFSET: i = f(f(i)) return i - ''', 96, + ''', 98, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOAD_GLOBAL") @@ -263,7 +263,7 @@ x = a.f(i) i = a.f(x) return i - ''', 92, + ''', 93, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOOKUP_METHOD") @@ -308,7 +308,7 @@ x = a.f(i) i = a.g(x) return i - ''', 105, + ''', 106, ([20], 20), ([31], 31)) ops = self.get_by_bytecode("LOOKUP_METHOD") Modified: pypy/branch/x86-64-jit-backend/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/sys/__init__.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/sys/__init__.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.interpreter.error import OperationError +from pypy.rlib.objectmodel import we_are_translated import sys class Module(MixedModule): @@ -92,8 +93,12 @@ self.space.setitem(w_modules, w_name, w_module) def startup(self, space): - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) + if space.config.translating and not we_are_translated(): + # don't get the filesystemencoding at translation time + assert self.filesystemencoding is None + else: + from pypy.module.sys.interp_encoding import _getfilesystemencoding + self.filesystemencoding = _getfilesystemencoding(space) def getmodule(self, name): space = self.space Modified: pypy/branch/x86-64-jit-backend/pypy/module/sys/app.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/sys/app.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/sys/app.py Fri Jun 18 20:55:39 2010 @@ -7,8 +7,35 @@ def excepthook(exctype, value, traceback): """Handle an exception by displaying it with a traceback on sys.stderr.""" - from traceback import print_exception - print_exception(exctype, value, traceback) + try: + from traceback import print_exception + print_exception(exctype, value, traceback) + except: + if not excepthook_failsafe(exctype, value): + raise + +def excepthook_failsafe(exctype, value): + # This version carefully tries to handle all bad cases (e.g. an + # ImportError looking for traceback.py), but may still raise. + # If it does, we get "Error calling sys.excepthook" from app_main.py. + try: + # first try to print the exception's class name + stderr = sys.stderr + stderr.write(getattr(exctype, '__name__', exctype)) + # then attempt to get the str() of the exception + try: + s = str(value) + except: + s = '' + # then print it, and don't worry too much about the extra space + # between the exception class and the ':' + if s: + stderr.write(': %s\n' % (s,)) + else: + stderr.write('\n') + return True # successfully printed at least the class and value + except: + return False # got an exception again... ignore, report the original def exit(exitcode=0): """Exit the interpreter by raising SystemExit(exitcode). Modified: pypy/branch/x86-64-jit-backend/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/sys/interp_encoding.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,6 @@ import sys from pypy.rlib import rlocale +from pypy.rlib.objectmodel import we_are_translated def getdefaultencoding(space): """Return the current default string encoding used by the Unicode @@ -18,6 +19,8 @@ space.sys.defaultencoding = encoding def get_w_default_encoder(space): + assert not (space.config.translating and not we_are_translated()), \ + "get_w_default_encoder() should not be called during translation" w_encoding = space.wrap(space.sys.defaultencoding) mod = space.getbuiltinmodule("_codecs") w_lookup = space.getattr(mod, space.wrap("lookup")) Modified: pypy/branch/x86-64-jit-backend/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/sys/test/test_sysmodule.py Fri Jun 18 20:55:39 2010 @@ -177,6 +177,26 @@ sys.stderr = savestderr assert err.getvalue().endswith("ValueError: 42\n") + def test_excepthook_failsafe_path(self): + import traceback + original_print_exception = traceback.print_exception + import cStringIO + savestderr = sys.stderr + err = cStringIO.StringIO() + sys.stderr = err + try: + traceback.print_exception = "foo" + eh = sys.__excepthook__ + try: + raise ValueError(42) + except ValueError, exc: + eh(*sys.exc_info()) + finally: + traceback.print_exception = original_print_exception + sys.stderr = savestderr + + assert err.getvalue() == "ValueError: 42\n" + # FIXME: testing the code for a lost or replaced excepthook in # Python/pythonrun.c::PyErr_PrintEx() is tricky. Modified: pypy/branch/x86-64-jit-backend/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/zipimport/interp_zipimport.py Fri Jun 18 20:55:39 2010 @@ -146,7 +146,7 @@ def import_py_file(self, space, modname, filename, buf, pkgpath): w = space.wrap w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) code_w = importing.parse_source_module(space, filename, buf) @@ -193,7 +193,7 @@ pkgpath) buf = buf[8:] # XXX ugly copy, should use sequential read instead w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) result = importing.load_compiled_module(space, w(modname), w_mod, @@ -223,11 +223,6 @@ def load_module(self, space, fullname): w = space.wrap - w_modules = space.sys.get('modules') - try: - return space.getitem(w_modules, w(fullname)) - except OperationError, e: - pass filename = self.mangle(fullname) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: @@ -242,7 +237,7 @@ pass else: if is_package: - pkgpath = self.name + pkgpath = self.name + os.path.sep + filename else: pkgpath = None try: @@ -351,7 +346,6 @@ raise operationerrfmt(w_ZipImportError, "Cannot import %s from zipfile, recursion detected or" "already tried and failed", name) - return w_result except KeyError: zip_cache.cache[filename] = None try: @@ -363,6 +357,8 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] + if prefix and not prefix.endswith(ZIPSEP): + prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) zip_cache.set(filename, w_result) Modified: pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_undocumented.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_undocumented.py Fri Jun 18 20:55:39 2010 @@ -118,7 +118,7 @@ import zipimport, os zip_path = self.temp_zipfile(self.created_paths) try: - prefix = '_pkg' + prefix = '_pkg/' path = os.path.join(zip_path, prefix) zip_importer = zipimport.zipimporter(path) assert isinstance(zip_importer, zipimport.zipimporter) Modified: pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/module/zipimport/test/test_zipimport.py Fri Jun 18 20:55:39 2010 @@ -114,10 +114,22 @@ from zipimport import _zip_directory_cache, zipimporter new_importer = zipimporter(self.zipfile) try: - assert zipimporter(self.zipfile) is new_importer + assert zipimporter(self.zipfile) is not new_importer finally: del _zip_directory_cache[self.zipfile] + def test_cache_subdir(self): + self.writefile(self, 'x.py', '') + self.writefile(self, 'sub/__init__.py', '') + self.writefile(self, 'sub/yy.py', '') + from zipimport import _zip_directory_cache, zipimporter + sub_importer = zipimporter(self.zipfile + '/sub') + main_importer = zipimporter(self.zipfile) + + assert main_importer is not sub_importer + assert main_importer.prefix == "" + assert sub_importer.prefix == "sub/" + def test_good_bad_arguments(self): from zipimport import zipimporter import os @@ -193,17 +205,50 @@ import zipimport z = zipimport.zipimporter(self.zipfile) sys.modules['uuu'] = lambda x : x + 1 - mod = z.load_module('uuu') - assert mod(3) == 4 + raises(ImportError, z.load_module, 'uuu') def test_package(self): import os, sys self.writefile(self, "xxuuu/__init__.py", "") self.writefile(self, "xxuuu/yy.py", "def f(x): return x") mod = __import__("xxuuu", globals(), locals(), ['yy']) - assert mod.__path__ + assert mod.__path__ == [self.zipfile + os.path.sep + "xxuuu"] + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuu" + os.path.sep + + "__init__.py") assert mod.yy.f(3) == 3 + def test_package_bug(self): + import os, sys + import new + mod = new.module('xxuuv') + mod.__path__ = [self.zipfile + '/xxuuv'] + sys.modules['xxuuv'] = mod + # + self.writefile(self, "xxuuv/__init__.py", "") + self.writefile(self, "xxuuv/yy.py", "def f(x): return x") + mod = __import__("xxuuv.yy", globals(), locals(), ['__doc__']) + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuv" + os.path.sep + + "yy.py") + assert mod.f(3) == 3 + + def test_pyc_in_package(self): + import os, sys + import new + mod = new.module('xxuuw') + mod.__path__ = [self.zipfile + '/xxuuw'] + sys.modules['xxuuw'] = mod + # + self.writefile(self, "xxuuw/__init__.py", "") + self.writefile(self, "xxuuw/zz.pyc", self.test_pyc) + mod = __import__("xxuuw.zz", globals(), locals(), ['__doc__']) + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuw" + os.path.sep + + "zz.pyc") + assert mod.get_file() == mod.__file__ + assert mod.get_name() == mod.__name__ + def test_functions(self): import os import zipimport @@ -241,7 +286,7 @@ archive = importer.archive realprefix = importer.prefix allbutlast = self.zipfile.split(os.path.sep)[:-1] - prefix = 'directory' + prefix = 'directory/' assert archive == self.zipfile assert realprefix == prefix Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/descroperation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/descroperation.py Fri Jun 18 20:55:39 2010 @@ -21,6 +21,13 @@ return w_setattr object_setattr._annspecialcase_ = 'specialize:memo' +def object_delattr(space): + "Utility that returns the app-level descriptor object.__delattr__." + w_src, w_delattr = space.lookup_in_type_where(space.w_object, + '__delattr__') + return w_delattr +object_delattr._annspecialcase_ = 'specialize:memo' + def raiseattrerror(space, w_obj, name, w_descr=None): w_type = space.type(w_obj) typename = w_type.getname(space, '?') Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/flow/model.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/flow/model.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/flow/model.py Fri Jun 18 20:55:39 2010 @@ -416,13 +416,14 @@ lst.append(link) return result -def copygraph(graph, shallow=False, varmap={}): +def copygraph(graph, shallow=False, varmap={}, shallowvars=False): "Make a copy of a flow graph." blockmap = {} varmap = varmap.copy() + shallowvars = shallowvars or shallow def copyvar(v): - if shallow: + if shallowvars: return v try: return varmap[v] Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/dictmultiobject.py Fri Jun 18 20:55:39 2010 @@ -467,7 +467,7 @@ # XXX fix this thing -import time, py +import time class DictInfo(object): _dict_infos = [] Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/dicttype.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/dicttype.py Fri Jun 18 20:55:39 2010 @@ -4,7 +4,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.stdtypedef import StdTypeDef, SMM, no_hash_descr from pypy.objspace.std.register_all import register_all -from pypy.interpreter.error import OperationError dict_copy = SMM('copy', 1, doc='D.copy() -> a shallow copy of D') Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/formatting.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/formatting.py Fri Jun 18 20:55:39 2010 @@ -474,12 +474,6 @@ [_name[-1] for _name in dir(StringFormatter) if len(_name) == 5 and _name.startswith('fmt_')]) -def is_list_of_chars_or_unichars(ann, bk): - from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint - if not isinstance(ann.listdef.listitem.s_value, - (SomeChar, SomeUnicodeCodePoint)): - raise TypeError("Formatter should return as a result a list of chars or unichars, otherwise we miss important optimization") - def format(space, w_fmt, values_w, w_valuedict=None, do_unicode=False): "Entry point" if not do_unicode: Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/frame.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/frame.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/frame.py Fri Jun 18 20:55:39 2010 @@ -130,7 +130,7 @@ w_result = getattr(f, attr)(w_1, w_2) break else: - raise pyopcde.BytecodeCorruption, "bad COMPARE_OP oparg" + raise pyopcode.BytecodeCorruption, "bad COMPARE_OP oparg" f.pushvalue(w_result) @@ -154,6 +154,7 @@ if space.config.objspace.std.optimized_comparison_op: StdObjSpaceFrame.COMPARE_OP = fast_COMPARE_OP if space.config.objspace.std.logspaceoptypes: + assert 0, "logspaceoptypes: a few fixes a missing here" StdObjSpace._space_op_types = [] for name, new in get_logging(): setattr(StdObjSpaceFrame, name, new) Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/settype.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/settype.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/settype.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr, SMM -from pypy.interpreter import gateway set_add = SMM('add', 2, doc='Add an element to a set.\n\nThis' Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/stringobject.py Fri Jun 18 20:55:39 2010 @@ -964,7 +964,6 @@ return mod_format(space, w_format, w_values, do_unicode=False) def buffer__String(space, w_string): - from pypy.interpreter.buffer import StringBuffer return space.wrap(StringBuffer(w_string._value)) # register all methods Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_floatobject.py Fri Jun 18 20:55:39 2010 @@ -92,9 +92,10 @@ def test_float_string(self): assert 42 == float("42") assert 42.25 == float("42.25") - assert str(float("inf")).startswith("inf") - assert str(float("-INf")).startswith("-inf") - assert str(float("-nAn")).startswith("nan") + inf = 1e200*1e200 + assert float("inf") == inf + assert float("-INf") == -inf + assert 'nan' in str(float("-nAn")).lower() def test_float_unicode(self): # u00A0 and u2000 are some kind of spaces Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_stringformat.py Fri Jun 18 20:55:39 2010 @@ -125,6 +125,15 @@ assert '27' == '%.2o' % n assert '027' == '%#.2o' % n + def test_format_long(self): + l = 4800000000L + assert '%d' % l == '4800000000' + # + class SubLong(long): + pass + sl = SubLong(l) + assert '%d' % sl == '4800000000' + def test_format_list(self): l = [1,2] assert '<[1, 2]>' == '<%s>' % l Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_strutil.py Fri Jun 18 20:55:39 2010 @@ -2,8 +2,6 @@ from pypy.objspace.std.strutil import * from pypy.interpreter.error import OperationError -import py - class TestStrUtil: Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_tupleobject.py Fri Jun 18 20:55:39 2010 @@ -289,7 +289,7 @@ assert (t * 1) is not t assert (t * 1) == t - def test_getslice(self): + def test_getslice_2(self): assert (5,2,3)[1:2] == (2,) def test_eq(self): Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_typeobject.py Fri Jun 18 20:55:39 2010 @@ -1001,12 +1001,12 @@ y.x = 3 assert y.x == 3 - def ga(self, name): - return 'GA' + def ga2(self, name): + return 'GA2' - X.__getattribute__ = ga + X.__getattribute__ = ga2 - assert y.x == 'GA' + assert y.x == 'GA2' class TestNewShortcut: Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_unicodeobject.py Fri Jun 18 20:55:39 2010 @@ -321,7 +321,7 @@ assert U(u'test') == u'test' assert U(u'test').__class__ is U - def test_call_unicode(self): + def test_call_unicode_2(self): class X(object): def __unicode__(self): return u'x' Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/transparent.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/transparent.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/transparent.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,6 @@ """ from pypy.interpreter import gateway -from pypy.interpreter.function import Function from pypy.interpreter.error import OperationError, operationerrfmt from pypy.objspace.std.proxyobject import * from pypy.objspace.std.typeobject import W_TypeObject Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/unicodetype.py Fri Jun 18 20:55:39 2010 @@ -3,6 +3,8 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.register_all import register_all from pypy.objspace.std.basestringtype import basestring_typedef +from pypy.rlib.runicode import str_decode_utf_8, str_decode_ascii,\ + unicode_encode_utf_8, unicode_encode_ascii from sys import maxint @@ -168,6 +170,32 @@ # ____________________________________________________________ +def decode_error_handler(space): + def raise_unicode_exception_decode(errors, encoding, msg, s, + startingpos, endingpos): + raise OperationError(space.w_UnicodeDecodeError, + space.newtuple([space.wrap(encoding), + space.wrap(s), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_decode +decode_error_handler._annspecialcase_ = 'specialize:memo' + +def encode_error_handler(space): + def raise_unicode_exception_encode(errors, encoding, msg, u, + startingpos, endingpos): + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([space.wrap(encoding), + space.wrap(u), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_encode +encode_error_handler._annspecialcase_ = 'specialize:memo' + +# ____________________________________________________________ + def getdefaultencoding(space): return space.sys.defaultencoding @@ -188,6 +216,17 @@ # This lookup is cached. w_encoder = space.sys.get_w_default_encoder() else: + if errors is None or errors == 'strict': + if encoding == 'ascii': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_ascii(u, len(u), None, + errorhandler=eh)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_utf_8(u, len(u), None, + errorhandler=eh)) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -203,9 +242,21 @@ return w_retval def decode_object(space, w_obj, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") if encoding is None: encoding = getdefaultencoding(space) + if errors is None or errors == 'strict': + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_ascii(s, len(s), None, + errorhandler=eh)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_utf_8(s, len(s), None, + errorhandler=eh)[0]) + w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: w_retval = space.call_function(w_decode, w_obj, space.wrap(encoding)) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/jit.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/jit.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/jit.py Fri Jun 18 20:55:39 2010 @@ -6,26 +6,56 @@ from pypy.rlib.unroll import unrolling_iterable def purefunction(func): + """ Decorate a function as pure. Pure means precisely that: + + (1) the result of the call should not change if the arguments are + the same (same numbers or same pointers) + (2) it's fine to remove the call completely if we can guess the result + according to rule 1 + + Most importantly it doesn't mean that pure function has no observable + side effect, but those side effects can be ommited (ie caching). + For now, such a function should never raise an exception. + """ func._pure_function_ = True return func def hint(x, **kwds): + """ Hint for the JIT + + possible arguments are: + XXX + """ return x def dont_look_inside(func): + """ Make sure the JIT does not trace inside decorated function + (it becomes a call instead) + """ func._jit_look_inside_ = False return func def unroll_safe(func): + """ JIT can safely unroll loops in this function and this will + not lead to code explosion + """ func._jit_unroll_safe_ = True return func def loop_invariant(func): + """ Describes a function with no argument that returns an object that + is always the same in a loop. + + Use it only if you know what you're doing. + """ dont_look_inside(func) func._jit_loop_invariant_ = True return func def purefunction_promote(promote_args='all'): + """ A decorator that promotes all arguments and then calls the supplied + function + """ def decorator(func): import inspect purefunction(func) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/libffi.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/libffi.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,4 @@ - -""" Various rpython-level functions for dlopen and libffi wrapping +""" Libffi wrapping """ from pypy.rpython.tool import rffi_platform @@ -7,15 +6,17 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.rmmap import alloc +from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal +from pypy.rlib.rdynload import DLOpenError from pypy.tool.autopath import pypydir from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rmmap import alloc +from pypy.translator.platform import platform import py import os import sys import ctypes.util -from pypy.translator.platform import platform # maaaybe isinstance here would be better. Think _MSVC = platform.name == "msvc" @@ -55,18 +56,13 @@ if _MINGW: includes = ['windows.h', 'ffi.h'] else: - includes = ['dlfcn.h', 'ffi.h'] + includes = ['ffi.h'] if _MAC_OS: pre_include_bits = ['#define MACOSX'] else: pre_include_bits = [] - if _FREEBSD_7 or _MINGW: - libraries = [] - else: - libraries = ['dl'] - def find_libffi_a(): dirlist = platform.library_dirs_for_libffi_a() for dir in dirlist: @@ -77,10 +73,11 @@ if hasattr(platform, 'library_dirs_for_libffi_a'): # platforms on which we want static linking + libraries = [] link_files = [find_libffi_a()] else: # platforms on which we want dynamic linking - libraries = ['ffi'] + libraries + libraries = ['ffi'] link_files = [] eci = ExternalCompilationInfo( @@ -115,10 +112,6 @@ class CConfig: _compilation_info_ = eci - RTLD_LOCAL = rffi_platform.DefinedConstantInteger('RTLD_LOCAL') - RTLD_GLOBAL = rffi_platform.DefinedConstantInteger('RTLD_GLOBAL') - RTLD_NOW = rffi_platform.DefinedConstantInteger('RTLD_NOW') - FFI_OK = rffi_platform.ConstantInteger('FFI_OK') FFI_BAD_TYPEDEF = rffi_platform.ConstantInteger('FFI_BAD_TYPEDEF') FFI_DEFAULT_ABI = rffi_platform.ConstantInteger('FFI_DEFAULT_ABI') @@ -216,61 +209,8 @@ def winexternal(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') -class DLOpenError(Exception): - def __init__(self, msg): - self.msg = msg - def __str__(self): - return repr(self.msg) - if not _WIN32: - c_dlopen = external('dlopen', [rffi.CCHARP, rffi.INT], rffi.VOIDP) - c_dlclose = external('dlclose', [rffi.VOIDP], rffi.INT) - c_dlerror = external('dlerror', [], rffi.CCHARP) - c_dlsym = external('dlsym', [rffi.VOIDP, rffi.CCHARP], rffi.VOIDP) - - RTLD_LOCAL = cConfig.RTLD_LOCAL - RTLD_GLOBAL = cConfig.RTLD_GLOBAL - RTLD_NOW = cConfig.RTLD_NOW - - def dlerror(): - # XXX this would never work on top of ll2ctypes, because - # ctypes are calling dlerror itself, unsure if I can do much in this - # area (nor I would like to) - res = c_dlerror() - if not res: - return "" - return rffi.charp2str(res) - - def dlopen(name, mode=-1): - """ Wrapper around C-level dlopen - """ - if mode == -1: - if RTLD_LOCAL is not None: - mode = RTLD_LOCAL | RTLD_NOW - else: - mode = RTLD_NOW - res = c_dlopen(name, rffi.cast(rffi.INT, mode)) - if not res: - err = dlerror() - raise DLOpenError(err) - return res - - dlclose = c_dlclose - - def dlsym(libhandle, name): - """ Wrapper around C-level dlsym - """ - res = c_dlsym(libhandle, name) - if not res: - raise KeyError(name) - # XXX rffi.cast here... - return res - - def dlsym_byordinal(handle, index): - # Never called - raise KeyError(index) - def check_fficall_result(result, flags): pass # No check @@ -281,36 +221,6 @@ return libc_name if _WIN32: - def dlopen(name): - res = rwin32.LoadLibrary(name) - if not res: - err = rwin32.GetLastError() - raise DLOpenError(rwin32.FormatError(err)) - return res - - def dlclose(handle): - res = rwin32.FreeLibrary(handle) - if res: - return -1 - else: - return 0 - - def dlsym(handle, name): - res = rwin32.GetProcAddress(handle, name) - if not res: - raise KeyError(name) - # XXX rffi.cast here... - return res - - def dlsym_byordinal(handle, index): - # equivalent to MAKEINTRESOURCEA - intresource = rffi.cast(rffi.CCHARP, r_uint(index) & 0xFFFF) - res = rwin32.GetProcAddress(handle, intresource) - if not res: - raise KeyError(name) - # XXX rffi.cast here... - return res - def check_fficall_result(result, flags): if result == 0: return Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/parsing/test/test_regexparse.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/parsing/test/test_regexparse.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/parsing/test/test_regexparse.py Fri Jun 18 20:55:39 2010 @@ -24,7 +24,7 @@ assert r.recognize("kjsadfq3jlflASDF@#$") assert r.recognize("vka afj ASF# A") -def test_quoted(): +def test_quoted_1(): r = make_runner("\\(*") assert r.recognize("(") assert not r.recognize("\\(") @@ -77,7 +77,7 @@ assert not r.recognize("a") assert not r.recognize("c") -def test_quoted(): +def test_quoted_2(): r = make_runner('\\[|\\]|\\|') assert r.recognize("[") assert r.recognize("|") Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/rarithmetic.py Fri Jun 18 20:55:39 2010 @@ -178,12 +178,6 @@ else: return super(base_int, klass).__new__(klass, val) - def __int__(self): - if self < LONG_TEST: - return long.__int__(self) - else: - return intmask(self) - def __add__(self, other): x = long(self) y = long(other) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/rgc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/rgc.py Fri Jun 18 20:55:39 2010 @@ -201,7 +201,6 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP - from pypy.rpython.lltypesystem import lltype hop.exception_is_here() return hop.genop('gc_heap_stats', [], resulttype=hop.r_result) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/runicode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/runicode.py Fri Jun 18 20:55:39 2010 @@ -17,7 +17,7 @@ # Note that Python3 uses a similar implementation. def UNICHR(c): assert not we_are_translated() - if c < sys.maxunicode or c > MAXUNICODE: + if c <= sys.maxunicode or c > MAXUNICODE: return unichr(c) else: c -= 0x10000 @@ -48,14 +48,12 @@ def raise_unicode_exception_decode(errors, encoding, msg, s, startingpos, endingpos): assert isinstance(s, str) - raise UnicodeDecodeError( - encoding, s[startingpos], startingpos, endingpos, msg) + raise UnicodeDecodeError(encoding, s, startingpos, endingpos, msg) def raise_unicode_exception_encode(errors, encoding, msg, u, startingpos, endingpos): assert isinstance(u, unicode) - raise UnicodeEncodeError( - encoding, u[startingpos], startingpos, endingpos, msg) + raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg) # ____________________________________________________________ # unicode decoding Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/rwin32.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/rwin32.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/rwin32.py Fri Jun 18 20:55:39 2010 @@ -7,6 +7,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import intmask +from pypy.rlib import jit import os, sys, errno # This module can be imported on any platform, @@ -198,6 +199,7 @@ [lltype.Ptr(OSVERSIONINFO)], DWORD) + @jit.dont_look_inside def GetVersionEx(): info = lltype.malloc(OSVERSIONINFO, flavor='raw') rffi.setintfield(info, 'c_dwOSVersionInfoSize', Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_libffi.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_libffi.py Fri Jun 18 20:55:39 2010 @@ -1,15 +1,14 @@ -""" Tests of libffi wrappers and dl* friends +""" Tests of libffi wrapper """ -from pypy.rpython.test.test_llinterp import interpret from pypy.translator.c.test.test_genc import compile from pypy.rlib.libffi import * from pypy.rlib.objectmodel import keepalive_until_here from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED from pypy.rpython.lltypesystem import rffi, lltype -import os, sys import py +import sys import time def setup_module(mod): @@ -19,14 +18,10 @@ ffistruct = globals()[name] rffi.cast(rffi.VOIDP, ffistruct) -class TestDLOperations: +class TestLibffi: def setup_method(self, meth): ALLOCATED.clear() - def test_dlopen(self): - py.test.raises(DLOpenError, "dlopen(rffi.str2charp('xxxxxxxxxxxx'))") - assert dlopen(rffi.str2charp(get_libc_name())) - def get_libc(self): return CDLL(get_libc_name()) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rarithmetic.py Fri Jun 18 20:55:39 2010 @@ -114,7 +114,10 @@ #self.binary_test(lambda x, y: pow(x, y, 42), (2, 3, 5, 1000)) def test_back_to_int(self): - assert int(r_uint(-1)) == -1 + #assert int(r_uint(-1)) == -1 + # ^^^ that looks wrong IMHO: int(x) should not by itself return + # an integer that has a different value than x, especially + # if x is a subclass of long. assert int(r_uint(1)) == 1 def unary_test(self, f): Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rbigint.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rbigint.py Fri Jun 18 20:55:39 2010 @@ -55,8 +55,6 @@ assert r1.tolong() == r2 def test_touint(self): - import sys - from pypy.rlib.rarithmetic import r_uint result = r_uint(sys.maxint + 42) rl = rbigint.fromint(sys.maxint).add(rbigint.fromint(42)) assert rl.touint() == result Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rlocale.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rlocale.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rlocale.py Fri Jun 18 20:55:39 2010 @@ -14,7 +14,8 @@ py.test.skip("polish locale unsupported") def teardown_class(cls): - setlocale(LC_ALL, cls.oldlocale) + if hasattr(cls, "oldlocale"): + setlocale(LC_ALL, cls.oldlocale) def test_setlocale_worked(self): assert u"??".isupper() Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rmmap.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rmmap.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rlib import rmmap as mmap from pypy.rlib.rmmap import RTypeError, RValueError, alloc, free -import sys class TestMMap: def setup_class(cls): Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rpoll.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_rpoll.py Fri Jun 18 20:55:39 2010 @@ -1,4 +1,4 @@ -import thread +import thread, errno from pypy.rlib.rsocket import * from pypy.rlib.rpoll import * from pypy.rpython.test.test_llinterp import interpret @@ -34,8 +34,10 @@ assert events[0][1] & POLLOUT err = cli.connect_ex(servaddr) - # win32 oddity: returns WSAEISCONN when the connection finally succeed. - assert err == 0 or err == 10056 + # win32: returns WSAEISCONN when the connection finally succeed. + # Mac OS/X: returns EISCONN. + assert (err == 0 or err == 10056 or + err == getattr(errno, 'EISCONN', '???')) events = poll({servconn.fileno(): POLLIN, cli.fileno(): POLLIN}, timeout=100) Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_runicode.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_runicode.py Fri Jun 18 20:55:39 2010 @@ -2,6 +2,16 @@ import sys, random from pypy.rlib import runicode +def test_unichr(): + a = runicode.UNICHR(0xffff) + assert a == u'\uffff' + a = runicode.UNICHR(0x10000) + if sys.maxunicode < 0x10000: + assert len(a) == 2 # surrogates + else: + assert len(a) == 1 + + class UnicodeTests(object): def typeequals(self, x, y): assert x == y @@ -217,6 +227,10 @@ self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? class TestTranslation(object): + def setup_class(cls): + if len(runicode.UNICHR(0x10000)) == 2: + py.test.skip("these tests cannot run on the llinterp") + def test_utf8(self): from pypy.rpython.test.test_llinterp import interpret def f(x): Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/llinterp.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/llinterp.py Fri Jun 18 20:55:39 2010 @@ -111,16 +111,14 @@ self.traceback_frames = [] lines = [] for frame in frames: - logline = frame.graph.name + logline = frame.graph.name + "()" if frame.curr_block is None: logline += " " lines.append(logline) continue try: - logline += " " + self.typer.annotator.annotated[frame.curr_block].__module__ - except (KeyError, AttributeError): - # if the graph is from the GC it was not produced by the same - # translator :-( + logline += " " + self.typer.annotator.annotated[frame.curr_block].func.__module__ + except (KeyError, AttributeError, TypeError): logline += " " lines.append(logline) for i, operation in enumerate(frame.curr_block.operations): @@ -808,9 +806,9 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) - def op_cast_adr_to_int(self, adr): + def op_cast_adr_to_int(self, adr, mode): checkadr(adr) - return llmemory.cast_adr_to_int(adr) + return llmemory.cast_adr_to_int(adr, mode) def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/ll2ctypes.py Fri Jun 18 20:55:39 2010 @@ -505,7 +505,7 @@ # additionally, this adds mess to __del__ "semantics" _all_callbacks = {} _all_callbacks_results = [] -_callback2obj = {} +_int2obj = {} _callback_exc_info = None def get_rtyper(): @@ -522,6 +522,13 @@ """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) + if isinstance(llobj, llmemory.AddressAsInt): + cobj = ctypes.cast(lltype2ctypes(llobj.adr), ctypes.c_void_p) + res = intmask(cobj.value) + _int2obj[res] = llobj.adr.ptr._obj + return res + if isinstance(llobj, llmemory.fakeaddress): + llobj = llobj.ptr or 0 T = lltype.typeOf(llobj) @@ -614,8 +621,9 @@ else: ctypes_func_type = get_ctypes_type(T) res = ctypes_func_type(callback) - _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container _all_callbacks[key] = res + key2 = intmask(ctypes.cast(res, ctypes.c_void_p).value) + _int2obj[key2] = container return res index = 0 @@ -724,9 +732,9 @@ container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): - cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value - if cobjkey in _callback2obj: - container = _callback2obj[cobjkey] + cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value) + if cobjkey in _int2obj: + container = _int2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), @@ -993,6 +1001,8 @@ """Cast a value to a result type, trying to use the same rules as C.""" if not isinstance(RESTYPE, lltype.LowLevelType): raise TypeError("rffi.cast() first arg should be a TYPE") + if isinstance(value, llmemory.AddressAsInt): + value = value.adr if isinstance(value, llmemory.fakeaddress): value = value.ptr or 0 TYPE1 = lltype.typeOf(value) Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llarena.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,5 @@ import array, weakref -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import llmemory # An "arena" is a large area of memory which can hold a number of # objects, not necessarily all of the same type or size. It's used by @@ -223,7 +223,8 @@ else: return self.arena._getid() < arena._getid() - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): + assert not symbolic return self.arena._getid() + self.offset Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/llmemory.py Fri Jun 18 20:55:39 2010 @@ -7,6 +7,7 @@ import weakref from pypy.rlib.objectmodel import Symbolic from pypy.rpython.lltypesystem import lltype +from pypy.tool.uid import uid class AddressOffset(Symbolic): @@ -478,11 +479,14 @@ else: return lltype.nullptr(EXPECTED_TYPE.TO) - def _cast_to_int(self): - # This is a bit annoying. We want this method to still work when the - # pointed-to object is dead + def _cast_to_int(self, symbolic=False): if self: - return self.ptr._cast_to_int(False) + if symbolic: + return AddressAsInt(self) + else: + # This is a bit annoying. We want this method to still work + # when the pointed-to object is dead + return self.ptr._cast_to_int(False) else: return 0 @@ -496,6 +500,29 @@ # ____________________________________________________________ +class AddressAsInt(Symbolic): + # a symbolic, rendered as an address cast to an integer. + def __init__(self, adr): + self.adr = adr + def annotation(self): + from pypy.annotation import model + return model.SomeInteger() + def lltype(self): + return lltype.Signed + def __eq__(self, other): + return self.adr == cast_int_to_adr(other) + def __ne__(self, other): + return self.adr != cast_int_to_adr(other) + def __nonzero__(self): + return bool(self.adr) + def __repr__(self): + try: + return '' % (self.adr.ptr,) + except AttributeError: + return '' % (uid(self),) + +# ____________________________________________________________ + class NullAddressError(Exception): pass @@ -603,12 +630,31 @@ def cast_adr_to_ptr(adr, EXPECTED_TYPE): return adr._cast_to_ptr(EXPECTED_TYPE) -def cast_adr_to_int(adr): - return adr._cast_to_int() +def cast_adr_to_int(adr, mode="emulated"): + # The following modes are supported before translation (after + # translation, it's all just a cast): + # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some + # number based on id(). The difference is that it works even if the + # address is that of a dead object. + # * mode="symbolic": returns an AddressAsInt instance, which can only be + # cast back to an address later. + # * mode="forced": uses rffi.cast() to return a real number. + assert mode in ("emulated", "symbolic", "forced") + res = adr._cast_to_int(symbolic = (mode != "emulated")) + if mode == "forced": + from pypy.rpython.lltypesystem.rffi import cast + res = cast(lltype.Signed, res) + return res _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + if isinstance(int, AddressAsInt): + return int.adr + try: + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + except ValueError: + from pypy.rpython.lltypesystem import ll2ctypes + ptr = ll2ctypes._int2obj[int]._as_ptr() return cast_ptr_to_adr(ptr) # ____________________________________________________________ Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lloperation.py Fri Jun 18 20:55:39 2010 @@ -227,6 +227,8 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), + 'int_between': LLOp(canfold=True), # a <= b < c + 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), # ^^^ more efficient version when 2nd arg is nonneg @@ -263,7 +265,7 @@ 'uint_rshift': LLOp(canfold=True), 'uint_xor': LLOp(canfold=True), - 'float_is_true': LLOp(canfold=True), + 'float_is_true': LLOp(canfold=True), # it really means "x != 0.0" 'float_neg': LLOp(canfold=True), 'float_abs': LLOp(canfold=True), @@ -410,7 +412,7 @@ 'cast_ptr_to_adr': LLOp(sideeffects=False), 'cast_adr_to_ptr': LLOp(canfold=True), 'cast_adr_to_int': LLOp(sideeffects=False), - 'cast_int_to_adr': LLOp(canfold=True), # not implemented in llinterp + 'cast_int_to_adr': LLOp(canfold=True), 'get_group_member': LLOp(canfold=True), 'get_next_group_member':LLOp(canfold=True), Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/lltype.py Fri Jun 18 20:55:39 2010 @@ -12,7 +12,6 @@ from pypy.lib.identity_dict import identity_dict from types import NoneType from sys import maxint -import struct import weakref TLS = tlsobject() @@ -301,9 +300,17 @@ class RttiStruct(Struct): _runtime_type_info = None + def _install_extras(self, rtti=False, **kwds): + if rtti: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, + name=self._name, + about=self)._obj + Struct._install_extras(self, **kwds) + def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + raise TypeError("attachRuntimeTypeInfo: %r must have been built " + "with the rtti=True argument" % (self,)) if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -1877,7 +1884,8 @@ def cast_int_to_ptr(PTRTYPE, oddint): if oddint == 0: return nullptr(PTRTYPE.TO) - assert oddint & 1, "only odd integers can be cast back to ptr" + if not (oddint & 1): + raise ValueError("only odd integers can be cast back to ptr") return _ptr(PTRTYPE, oddint, solid=True) def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/opimpl.py Fri Jun 18 20:55:39 2010 @@ -197,6 +197,12 @@ assert isinstance(y, int) return intmask(x - y) +def op_int_between(a, b, c): + assert lltype.typeOf(a) is lltype.Signed + assert lltype.typeOf(b) is lltype.Signed + assert lltype.typeOf(c) is lltype.Signed + return a <= b < c + def op_int_and(x, y): if not isinstance(x, int): from pypy.rpython.lltypesystem import llgroup Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rclass.py Fri Jun 18 20:55:39 2010 @@ -13,8 +13,8 @@ Ptr, Struct, GcStruct, malloc, \ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ - Array, Char, Void, attachRuntimeTypeInfo, \ - FuncType, Bool, Signed, functionptr, FuncType, PyObject + Array, Char, Void, \ + FuncType, Bool, Signed, functionptr, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry @@ -22,6 +22,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel from pypy.lib.identity_dict import identity_dict +from pypy.rpython.lltypesystem.lloperation import llop # # There is one "vtable" per user class, with the following structure: @@ -60,7 +61,8 @@ CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), hints = {'immutable': True, 'shouldntbenull': True, - 'typeptr': True}) + 'typeptr': True}, + rtti = True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), @@ -72,7 +74,7 @@ hints = {'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) -NONGCOBJECTPTR = Ptr(OBJECT) +NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} @@ -348,18 +350,20 @@ if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) + kwds = {} + if self.gcflavor == 'gc': + kwds['rtti'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, - *llfields) + *llfields, + **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields - if self.gcflavor == 'gc': - attachRuntimeTypeInfo(self.object_type) def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) @@ -642,10 +646,12 @@ return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): - return cls.subclassrange_min <= subcls.subclassrange_min <= cls.subclassrange_max + return llop.int_between(Bool, cls.subclassrange_min, + subcls.subclassrange_min, + cls.subclassrange_max) def ll_issubclass_const(subcls, minid, maxid): - return minid <= subcls.subclassrange_min <= maxid + return llop.int_between(Bool, minid, subcls.subclassrange_min, maxid) def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rffi.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr -from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof, raw_memcopy +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic @@ -11,7 +11,6 @@ from pypy.rlib import rarithmetic, rgc from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.annlowlevel import llhelper @@ -645,7 +644,7 @@ """ str_chars_offset = (offsetof(STRTYPE, 'chars') + \ itemoffsetof(STRTYPE.chars, 0)) - gc_buf = lltype.nullptr(STRTYPE) # rgc.malloc_nonmovable(STRTYPE, count) + gc_buf = rgc.malloc_nonmovable(STRTYPE, count) if gc_buf: realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset raw_buf = cast(TYPEP, realbuf) @@ -785,7 +784,6 @@ # the hint is present in structures probed by rffi_platform. size = tp._hints.get('size') if size is None: - from pypy.rpython.lltypesystem import llmemory size = llmemory.sizeof(tp) # a symbolic result in this case return size if isinstance(tp, lltype.Ptr): @@ -814,7 +812,6 @@ if name == fieldname: return fieldoffsets[index] # a symbolic result as a fallback - from pypy.rpython.lltypesystem import llmemory return llmemory.offsetof(STRUCT, fieldname) offsetof._annspecialcase_ = 'specialize:memo' Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rlist.py Fri Jun 18 20:55:39 2010 @@ -388,6 +388,7 @@ ('index', Signed))) self.ll_listiter = ll_listiter self.ll_listnext = ll_listnext + self.ll_getnextindex = ll_getnextindex def ll_listiter(ITERPTR, lst): iter = malloc(ITERPTR.TO) @@ -402,3 +403,6 @@ raise StopIteration iter.index = index + 1 # cannot overflow because index < l.length return l.ll_getitem_fast(index) + +def ll_getnextindex(iter): + return iter.index Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Fri Jun 18 20:55:39 2010 @@ -15,7 +15,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper -from pypy.tool.udir import udir class TestLL2Ctypes(object): @@ -1242,6 +1241,15 @@ res = interpret(f, []) assert res == 6 + def test_force_to_int(self): + S = lltype.Struct('S') + p = lltype.malloc(S, flavor='raw') + a = llmemory.cast_ptr_to_adr(p) + i = llmemory.cast_adr_to_int(a, "forced") + assert type(i) is int + assert i == llmemory.cast_adr_to_int(a, "forced") + lltype.free(p, flavor='raw') + class TestPlatform(object): def test_lib_on_libpaths(self): from pypy.translator.platform import platform Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_llmemory.py Fri Jun 18 20:55:39 2010 @@ -624,3 +624,24 @@ # the following line crashes if the array is dead ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) ptr1[0] = NULL + +def test_cast_adr_to_int(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + i = cast_adr_to_int(adr, mode="symbolic") + assert isinstance(i, AddressAsInt) + assert cast_int_to_adr(i) == adr + assert cast_adr_to_int(NULL, mode="symbolic") == 0 + assert cast_int_to_adr(0) == NULL + # + i = cast_adr_to_int(adr, mode="emulated") + assert type(i) is int + i = cast_adr_to_int(NULL, mode="emulated") + assert type(i) is int and i == 0 + # + i = cast_adr_to_int(adr, mode="forced") + assert type(i) is int + #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details + i = cast_adr_to_int(NULL, mode="forced") + assert type(i) is int and i == 0 Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/test/test_lltype.py Fri Jun 18 20:55:39 2010 @@ -363,22 +363,25 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) py.test.raises(ValueError, "getRuntimeTypeInfo(S)") - pinf0 = attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) + pinfx = getRuntimeTypeInfo(S) + pinf0 = attachRuntimeTypeInfo(S) # no-op, really assert pinf0._obj.about == S + assert pinf0 == pinfx pinf = getRuntimeTypeInfo(S) assert pinf == pinf0 pinf1 = getRuntimeTypeInfo(S) assert pinf == pinf1 - Z = GcStruct('z', ('x', Unsigned)) - attachRuntimeTypeInfo(Z) + Z = GcStruct('z', ('x', Unsigned), rtti=True) assert getRuntimeTypeInfo(Z) != pinf0 - Sbis = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(Sbis) + Sbis = GcStruct('s', ('x', Signed), rtti=True) assert getRuntimeTypeInfo(Sbis) != pinf0 assert Sbis != S # the attached runtime type info distinguishes them + Ster = GcStruct('s', ('x', Signed), rtti=True) + assert Sbis != Ster # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -399,12 +402,12 @@ assert pinf._obj.query_funcptr == qp def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) attachRuntimeTypeInfo(S) s = malloc(S) s.x = 0 assert runtime_type_info(s) == getRuntimeTypeInfo(S) - S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + S1 = GcStruct('s1', ('sub', S), ('x', Signed), rtti=True) attachRuntimeTypeInfo(S1) s1 = malloc(S1) s1.sub.x = 0 @@ -719,7 +722,6 @@ def test_name_clash(): import re - from pypy.rpython.lltypesystem import lltype fn = lltype.__file__ if fn.lower().endswith('pyc') or fn.lower().endswith('pyo'): fn = fn[:-1] Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/generation.py Fri Jun 18 20:55:39 2010 @@ -720,7 +720,7 @@ return pos elif sys.platform == 'darwin': - from pypy.rpython.lltypesystem import lltype, rffi + from pypy.rpython.lltypesystem import rffi sysctlbyname = rffi.llexternal('sysctlbyname', [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP, Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gc/marksweep.py Fri Jun 18 20:55:39 2010 @@ -242,7 +242,6 @@ # 3. walk the list of objects-with-del and for the ones not marked: # call __del__, move the object to the list of object-without-del import time - from pypy.rpython.lltypesystem.lloperation import llop debug_start("gc-collect") start_time = time.time() self.collect_in_progress = True Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/asmgcroot.py Fri Jun 18 20:55:39 2010 @@ -114,12 +114,14 @@ fnptr._obj._name + '_reload', graph=graph2) c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2)], FUNC1.RESULT) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], resulttype=lltype.Ptr(HELPERFUNC)) hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, Constant(None, lltype.Void)], + [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, + Constant(None, lltype.Void)], resultvar=hop.spaceop.result) self.pop_roots(hop, livevars) @@ -151,7 +153,8 @@ def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata gcdata._gc_collect_stack_root = collect_stack_root - pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback)) + pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback), + gcrootanchor) def walk_stack_from(self): curframe = lltype.malloc(WALKFRAME, flavor='raw') @@ -160,7 +163,7 @@ # Walk over all the pieces of stack. They are in a circular linked # list of structures of 7 words, the 2 first words being prev/next. # The anchor of this linked list is: - anchor = llop.gc_asmgcroot_static(llmemory.Address, 3) + anchor = llmemory.cast_ptr_to_adr(gcrootanchor) initialframedata = anchor.address[1] stackscount = 0 while initialframedata != anchor: # while we have not looped back @@ -475,8 +478,22 @@ llmemory.Address), ) +# We have a circular doubly-linked list of all the ASM_FRAMEDATAs currently +# alive. The list's starting point is given by 'gcrootanchor', which is not +# a full ASM_FRAMEDATA but only contains the prev/next pointers: +ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference()) +ASM_FRAMEDATA_HEAD_PTR.TO.become(lltype.Struct('ASM_FRAMEDATA_HEAD', + ('prev', ASM_FRAMEDATA_HEAD_PTR), + ('next', ASM_FRAMEDATA_HEAD_PTR) + )) +gcrootanchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, immortal=True) +gcrootanchor.prev = gcrootanchor +gcrootanchor.next = gcrootanchor +c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', - [ASM_CALLBACK_PTR], + [ASM_CALLBACK_PTR, + ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True) Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_boehm.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_boehm.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_boehm.py Fri Jun 18 20:55:39 2010 @@ -40,7 +40,7 @@ assert f is not None def test_boehm_finalizer___del__(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -58,7 +58,8 @@ assert f is not None def test_boehm_finalizer_nomix___del___and_pyobj(): - S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) + S = lltype.GcStruct("S", ('x', lltype.Signed), + ('y', lltype.Ptr(lltype.PyObject)), rtti=True) def f(s): s.x = 1 def type_info_S(p): Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/gctransform/test/test_refcounting.py Fri Jun 18 20:55:39 2010 @@ -175,7 +175,7 @@ assert len(ops['gc_free']) == 1 def test_deallocator_with_destructor(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -192,9 +192,9 @@ graph, t = make_deallocator(S) def test_caching_dynamic_deallocator(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) - T = lltype.GcStruct("T", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) + S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) + T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/memory/test/test_lldict.py Fri Jun 18 20:55:39 2010 @@ -100,7 +100,7 @@ _TYPE = llmemory.Address def __init__(self, intval): self.intval = intval - def _cast_to_int(self): + def _cast_to_int(self, symbolic="?"): return self.intval def __repr__(self): return '' % (self.intval & (sys.maxint*2+1),) Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/normalizecalls.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/normalizecalls.py Fri Jun 18 20:55:39 2010 @@ -292,6 +292,13 @@ else: return cmp(self.orderwitness, other.orderwitness) + # support for implementing int_between: (a<=b 5: + key = llmemory.cast_ptr_to_adr(a) + else: + key = llmemory.cast_ptr_to_adr(b) + return d[key] + + assert self.interpret(func, [3]) == 456 + def test_prebuilt_list_of_addresses(self): from pypy.rpython.lltypesystem import llmemory Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rfloat.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rfloat.py Fri Jun 18 20:55:39 2010 @@ -77,7 +77,6 @@ assert res == fn(2.34) def test_longlong_conversion(self): - import sys def fn(f): return r_longlong(f) Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rint.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rint.py Fri Jun 18 20:55:39 2010 @@ -169,7 +169,6 @@ assert res == 0 def test_truediv(self): - import operator def f(n, m): return operator.truediv(n, m) res = self.interpret(f, [20, 4]) Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rlist.py Fri Jun 18 20:55:39 2010 @@ -10,7 +10,6 @@ from pypy.rpython.lltypesystem import rlist as ll_rlist from pypy.rpython.ootypesystem import rlist as oo_rlist from pypy.rpython.rint import signed_repr -from pypy.translator.translator import TranslationContext from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin @@ -1070,7 +1069,7 @@ assert res == 0 - def test_getitem_exc(self): + def test_getitem_exc_1(self): def f(x): l = [1] return l[x] @@ -1115,7 +1114,7 @@ res = self.interpret(f, [0]) assert res == 1 - def test_getitem_exc(self): + def test_getitem_exc_2(self): def f(x): l = [1] return l[x] Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rptr.py Fri Jun 18 20:55:39 2010 @@ -36,8 +36,7 @@ assert s.ll_ptrtype == PS2 def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def ll_example(p): return (runtime_type_info(p), runtime_type_info(p) == getRuntimeTypeInfo(S)) @@ -176,6 +175,31 @@ res = interpret(fn, [5]) assert res is True +def test_cast_adr_to_int(): + S = Struct('S') + p = malloc(S, immortal=True) + def fn(n): + a = llmemory.cast_ptr_to_adr(p) + if n == 2: + return llmemory.cast_adr_to_int(a, "emulated") + elif n == 4: + return llmemory.cast_adr_to_int(a, "symbolic") + else: + return llmemory.cast_adr_to_int(a, "forced") + + res = interpret(fn, [2]) + assert type(res) is int + assert res == cast_ptr_to_int(p) + # + res = interpret(fn, [4]) + assert isinstance(res, llmemory.AddressAsInt) + assert llmemory.cast_int_to_adr(res) == llmemory.cast_ptr_to_adr(p) + # + res = interpret(fn, [6]) + assert type(res) is int + from pypy.rpython.lltypesystem import rffi + assert res == rffi.cast(Signed, p) + def test_flavored_malloc(): T = GcStruct('T', ('y', Signed)) def fn(n): Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rrange.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rrange.py Fri Jun 18 20:55:39 2010 @@ -160,6 +160,15 @@ res = self.interpret(fn, []) assert res == 0 + def test_enumerate(self): + def fn(n): + for i, x in enumerate([123, 456, 789, 654]): + if i == n: + return x + return 5 + res = self.interpret(fn, [2]) + assert res == 789 + class TestLLtype(BaseTestRrange, LLRtypeMixin): from pypy.rpython.lltypesystem import rrange Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rvirtualizable2.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rvirtualizable2.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/test/test_rvirtualizable2.py Fri Jun 18 20:55:39 2010 @@ -311,7 +311,7 @@ assert res == 2323 def test_access_directly_stop_at_dont_look_inside(self): - from pypy.rlib.jit import hint, dont_look_inside + from pypy.rlib.jit import dont_look_inside class A: _virtualizable2_ = ['x'] Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/rpython/tool/rffi_platform.py Fri Jun 18 20:55:39 2010 @@ -752,7 +752,7 @@ 'struct sockaddr_in' sin_port INT """ - import sys, getopt + import getopt opts, args = getopt.gnu_getopt(sys.argv[1:], 'h:') if not args: print >> sys.stderr, doc Modified: pypy/branch/x86-64-jit-backend/pypy/tool/gcc_cache.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/gcc_cache.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/gcc_cache.py Fri Jun 18 20:55:39 2010 @@ -1,6 +1,5 @@ - from pypy.tool.autopath import pypydir -from pypy.translator.platform import platform, CompilationError +from pypy.translator.platform import CompilationError from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.compat import md5 import py @@ -8,6 +7,9 @@ cache_dir_root = py.path.local(pypydir).join('_cache').ensure(dir=1) def cache_file_path(c_files, eci, cachename): + "Builds a filename to cache compilation data" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform cache_dir = cache_dir_root.join(cachename).ensure(dir=1) filecontents = [c_file.read() for c_file in c_files] key = repr((filecontents, eci, platform.key())) @@ -15,6 +17,9 @@ return cache_dir.join(hash) def build_executable_cache(c_files, eci): + "Builds and run a program; caches the result" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'build_executable_cache') try: return path.read() @@ -24,6 +29,9 @@ return result.out def try_compile_cache(c_files, eci): + "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() @@ -33,9 +41,9 @@ try: platform.compile(c_files, eci) data = 'True' + path.write(data) except CompilationError, e: data = 'FAIL\n%s\n' % (e,) - path.write(data) if data.startswith('True'): return True else: Modified: pypy/branch/x86-64-jit-backend/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/pytest/appsupport.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/pytest/appsupport.py Fri Jun 18 20:55:39 2010 @@ -86,11 +86,18 @@ if debug_excs: self._excinfo = debug_excs[0] + def __repr__(self): + return "" % self.operr.errorstr(self.space) + def exconly(self, tryshort=True): return '(application-level) ' + self.operr.errorstr(self.space) def errisinstance(self, exc): clsname = exc.__name__ + # we can only check for builtin exceptions + # as there is no canonical applevel one for custom interplevel ones + if exc.__module__ != "exceptions": + return False try: w_exc = getattr(self.space, 'w_' + clsname) except KeyboardInterrupt: Modified: pypy/branch/x86-64-jit-backend/pypy/tool/pytest/test/test_appsupport.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/pytest/test/test_appsupport.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/pytest/test/test_appsupport.py Fri Jun 18 20:55:39 2010 @@ -113,6 +113,19 @@ "*E*application-level*NameError*x*not defined", ]) +def test_applevel_raise_keyerror(testdir): + setpypyconftest(testdir) + p = testdir.makepyfile(""" + def app_test_raises(): + raise KeyError(42) + pass + """) + result = testdir.runpytest(p, "-s") + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "*E*application-level*KeyError*42*", + ]) + def app_test_raises(): info = raises(TypeError, id) assert info.type is TypeError Modified: pypy/branch/x86-64-jit-backend/pypy/tool/runsubprocess.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/runsubprocess.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/runsubprocess.py Fri Jun 18 20:55:39 2010 @@ -5,7 +5,6 @@ import sys import os -import warnings from subprocess import PIPE, Popen def run_subprocess(executable, args, env=None, cwd=None): @@ -28,7 +27,9 @@ if __name__ == '__main__': + import gc while True: + gc.collect() operation = sys.stdin.readline() if not operation: sys.exit() @@ -46,16 +47,26 @@ # do this at import-time, when the process is still tiny _source = os.path.dirname(os.path.abspath(__file__)) _source = os.path.join(_source, 'runsubprocess.py') # and not e.g. '.pyc' - # Let's not hear about os.popen2's deprecation. - warnings.filterwarnings("ignore", ".*popen2.*", DeprecationWarning, - "pypy.tool.runsubprocess") - _child_stdin, _child_stdout = os.popen2( - "'%s' '%s'" % (sys.executable, _source)) + + def spawn_subprocess(): + global _child + _child = Popen([sys.executable, _source], bufsize=0, + stdin=PIPE, stdout=PIPE, close_fds=True) + spawn_subprocess() + + def cleanup_subprocess(): + global _child + _child = None + import atexit; atexit.register(cleanup_subprocess) def _run(*args): - _child_stdin.write('%r\n' % (args,)) - _child_stdin.flush() - results = _child_stdout.readline() + try: + _child.stdin.write('%r\n' % (args,)) + except (OSError, IOError): + # lost the child. Try again... + spawn_subprocess() + _child.stdin.write('%r\n' % (args,)) + results = _child.stdout.readline() assert results.startswith('(') results = eval(results) if results[0] is None: Modified: pypy/branch/x86-64-jit-backend/pypy/tool/sourcetools.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/sourcetools.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/sourcetools.py Fri Jun 18 20:55:39 2010 @@ -129,7 +129,6 @@ for name in names: if name not in kwargs: kwargs[name] = getattr(fromcode, name) - import new return new.code( kwargs['co_argcount'], kwargs['co_nlocals'], @@ -227,6 +226,12 @@ f.func_dict.update(func.func_dict) return f +def func_renamer(newname): + """A function decorator which changes the name of a function.""" + def decorate(func): + return func_with_new_name(func, newname) + return decorate + PY_IDENTIFIER = ''.join([(('0' <= chr(i) <= '9' or 'a' <= chr(i) <= 'z' or 'A' <= chr(i) <= 'Z') and chr(i) or '_') Modified: pypy/branch/x86-64-jit-backend/pypy/tool/test/test_runsubprocess.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/tool/test/test_runsubprocess.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/tool/test/test_runsubprocess.py Fri Jun 18 20:55:39 2010 @@ -30,3 +30,12 @@ assert returncode == 1 assert stdout == '' assert 'no/such/filename' in stderr + +def test_recover_lost_process(): + if not hasattr(os, 'fork'): + py.test.skip("there is no os.fork()") + from pypy.tool import runsubprocess + import signal + os.kill(runsubprocess._child.pid, signal.SIGTERM) + runsubprocess._child.wait() + test_echo() Modified: pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/storesink.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/storesink.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/storesink.py Fri Jun 18 20:55:39 2010 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem.lloperation import llop +from pypy.translator.backendopt import removenoops def has_side_effects(op): if op.opname == 'debug_assert': @@ -10,30 +11,27 @@ return True def storesink_graph(graph): - def rename(op, renaming): - for i, arg in enumerate(op.args): - r = renaming.get(arg, None) - if r is not None: - op.args[i] = r - return op def clear_cache_for(cache, concretetype, fieldname): for k in cache.keys(): if k[0].concretetype == concretetype and k[1] == fieldname: del cache[k] + + added_some_same_as = False for block in graph.iterblocks(): newops = [] cache = {} - renaming = {} for op in block.operations: if op.opname == 'getfield': tup = (op.args[0], op.args[1].value) res = cache.get(tup, None) if res is not None: - renaming[op.result] = res - continue - cache[tup] = op.result + op.opname = 'same_as' + op.args = [res] + added_some_same_as = True + else: + cache[tup] = op.result elif op.opname in ['setarrayitem', 'setinteriorfield']: pass elif op.opname == 'setfield': @@ -41,9 +39,9 @@ op.args[1].value) elif has_side_effects(op): cache = {} - newops.append(rename(op, renaming)) + newops.append(op) if block.operations: block.operations = newops - for exit in block.exits: - rename(exit, renaming) - + + if added_some_same_as: + removenoops.remove_same_as(graph) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/test/test_storesink.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/test/test_storesink.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/backendopt/test/test_storesink.py Fri Jun 18 20:55:39 2010 @@ -2,6 +2,7 @@ import py from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.storesink import storesink_graph +from pypy.translator.backendopt import removenoops from pypy.objspace.flow.model import last_exception, checkgraph from pypy.conftest import option @@ -19,6 +20,7 @@ t = self.translate(f, argtypes) getfields = 0 graph = graphof(t, f) + removenoops.remove_same_as(graph) checkgraph(graph) storesink_graph(graph) checkgraph(graph) @@ -119,3 +121,17 @@ return one + two self.check(f, [int], 2) + + def test_bug_1(self): + class A(object): + pass + + def f(i): + a = A() + a.cond = i > 0 + n = a.cond + if a.cond: + return True + return n + + self.check(f, [int], 1) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/benchmark/benchmarks.py Fri Jun 18 20:55:39 2010 @@ -85,8 +85,9 @@ def run_templess(executable, sizefactor=1): """ run some script in the templess package - templess is some simple templating language, to check out use - 'svn co -r100 http://johnnydebris.net/templess/trunk templess' + templess is some simple templating language. + We have a copy at + 'http://codespeak.net/svn/user/arigo/hack/pypy-hack/templess' """ here = py.path.local(__file__).dirpath() pypath = os.path.dirname(os.path.dirname(py.__file__)) @@ -107,8 +108,7 @@ def check_templess(): return external_dependency('templess', - 'http://johnnydebris.net/templess/trunk', - 100) + 'http://codespeak.net/svn/user/arigo/hack/pypy-hack/templess') def run_gadfly(executable, sizefactor=1): """ run some tests in the gadfly pure Python database """ Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/funcgen.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/funcgen.py Fri Jun 18 20:55:39 2010 @@ -318,6 +318,7 @@ def gen_op(self, op): macro = 'OP_%s' % op.opname.upper() + line = None if op.opname.startswith('gc_'): meth = getattr(self.gcpolicy, macro, None) if meth: @@ -326,7 +327,7 @@ meth = getattr(self, macro, None) if meth: line = meth(op) - if meth is None: + if line is None: lst = [self.expr(v) for v in op.args] lst.append(self.expr(op.result)) line = '%s(%s);' % (macro, ', '.join(lst)) @@ -849,5 +850,16 @@ return 'PYPY_DEBUG_CATCH_EXCEPTION("%s", %s, %s);' % ( self.getdebugfunctionname(), gottype, ' || '.join(exprs)) + def OP_INT_BETWEEN(self, op): + if (isinstance(op.args[0], Constant) and + isinstance(op.args[2], Constant) and + op.args[2].value - op.args[0].value == 1): + # (a <= b < a+1) ----> (b == a) + return '%s = (%s == %s); /* was INT_BETWEEN */' % ( + self.expr(op.result), + self.expr(op.args[1]), + self.expr(op.args[0])) + else: + return None # use the default assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/test/test_asmgcroot.py Fri Jun 18 20:55:39 2010 @@ -65,8 +65,13 @@ env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),) else: env = '' - g = os.popen( - '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + cwd = os.getcwd() + try: + os.chdir(str(exe_name.dirpath())) + g = os.popen( + '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + finally: + os.chdir(cwd) for line in g: print >> sys.stderr, 'RUN:', line.rstrip() lines.append(line) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/gcc/trackgcroot.py Fri Jun 18 20:55:39 2010 @@ -1283,20 +1283,13 @@ if self.format == 'msvc': print >> output, """\ - /* A circular doubly-linked list of all - * the ASM_FRAMEDATAs currently alive - */ - struct asm_framedata { - struct asm_framedata* prev; - struct asm_framedata* next; - } __gcrootanchor = { &__gcrootanchor, &__gcrootanchor }; - /* See description in asmgcroot.py */ __declspec(naked) long pypy_asm_stackwalk(void *callback) { __asm { - mov\tedx, DWORD PTR [esp+4]\t; my argument, which is the callback + mov\tedx, DWORD PTR [esp+4]\t; 1st argument, which is the callback + mov\tecx, DWORD PTR [esp+8]\t; 2nd argument, which is gcrootanchor mov\teax, esp\t\t; my frame top address push\teax\t\t\t; ASM_FRAMEDATA[6] push\tebp\t\t\t; ASM_FRAMEDATA[5] @@ -1307,10 +1300,10 @@ ; Add this ASM_FRAMEDATA to the front of the circular linked ; list. Let's call it 'self'. - mov\teax, DWORD PTR [__gcrootanchor+4]\t\t; next = gcrootanchor->next + mov\teax, DWORD PTR [ecx+4]\t\t; next = gcrootanchor->next push\teax\t\t\t\t\t\t\t\t\t; self->next = next - push\tOFFSET __gcrootanchor ; self->prev = gcrootanchor - mov\tDWORD PTR [__gcrootanchor+4], esp\t\t; gcrootanchor->next = self + push\tecx ; self->prev = gcrootanchor + mov\tDWORD PTR [ecx+4], esp\t\t; gcrootanchor->next = self mov\tDWORD PTR [eax+0], esp\t\t\t\t\t; next->prev = self call\tedx\t\t\t\t\t\t; invoke the callback @@ -1343,7 +1336,8 @@ print >> output, """\ /* See description in asmgcroot.py */ - movl\t4(%esp), %edx\t/* my argument, which is the callback */ + movl\t4(%esp), %edx\t/* 1st argument, which is the callback */ + movl\t8(%esp), %ecx\t/* 2nd argument, which is gcrootanchor */ movl\t%esp, %eax\t/* my frame top address */ pushl\t%eax\t\t/* ASM_FRAMEDATA[6] */ pushl\t%ebp\t\t/* ASM_FRAMEDATA[5] */ @@ -1354,10 +1348,10 @@ /* Add this ASM_FRAMEDATA to the front of the circular linked */ /* list. Let's call it 'self'. */ - movl\t__gcrootanchor + 4, %eax\t/* next = gcrootanchor->next */ + movl\t4(%ecx), %eax\t/* next = gcrootanchor->next */ pushl\t%eax\t\t\t\t/* self->next = next */ - pushl\t$__gcrootanchor\t\t\t/* self->prev = gcrootanchor */ - movl\t%esp, __gcrootanchor + 4\t/* gcrootanchor->next = self */ + pushl\t%ecx\t\t\t/* self->prev = gcrootanchor */ + movl\t%esp, 4(%ecx)\t/* gcrootanchor->next = self */ movl\t%esp, 0(%eax)\t\t\t/* next->prev = self */ /* note: the Mac OS X 16 bytes aligment must be respected. */ @@ -1378,7 +1372,7 @@ /* the return value is the one of the 'call' above, */ /* because %eax (and possibly %edx) are unmodified */ ret - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) + """ _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk', darwin='', @@ -1388,17 +1382,6 @@ for label, state, is_range in self.gcmaptable: label = label[1:] print >> output, "extern void* %s;" % label - else: - print >> output, """\ - /* A circular doubly-linked list of all */ - /* the ASM_FRAMEDATAs currently alive */ - .data - .align 4 - .globl __gcrootanchor - __gcrootanchor: - .long\t__gcrootanchor /* prev */ - .long\t__gcrootanchor /* next */ - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) shapes = {} shapelines = [] @@ -1437,6 +1420,8 @@ """ else: print >> output, """\ + .data + .align 4 .globl __gcmapstart __gcmapstart: """.replace("__gcmapstart", _globalname("__gcmapstart")) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/genc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/genc.py Fri Jun 18 20:55:39 2010 @@ -227,7 +227,7 @@ funcgen.patch_graph(copy_graph=False) return db - def generate_source(self, db=None, defines={}): + def generate_source(self, db=None, defines={}, exe_name=None): assert self.c_source_filename is None translator = self.translator @@ -271,7 +271,7 @@ defines = defines) self.c_source_filename = py.path.local(cfile) self.extrafiles = self.eventually_copy(extra) - self.gen_makefile(targetdir) + self.gen_makefile(targetdir, exe_name=exe_name) return cfile def eventually_copy(self, cfiles): @@ -482,7 +482,7 @@ # build main program eci = self.get_eci() kw = {} - if self.translator.platform.so_ext == 'so': + if self.translator.platform.cc == 'gcc': kw['libraries'] = [self.shared_library_name.purebasename[3:]] kw['library_dirs'] = [self.targetdir] else: @@ -516,6 +516,10 @@ extra_opts += ['-j', str(self.config.translation.make_jobs)] self.translator.platform.execute_makefile(self.targetdir, extra_opts) + if shared: + self.shared_library_name = self.executable_name.new( + purebasename='lib' + self.executable_name.purebasename, + ext=self.translator.platform.so_ext) else: compiler = CCompilerDriver(self.translator.platform, [self.c_source_filename] + self.extrafiles, @@ -531,6 +535,8 @@ def gen_makefile(self, targetdir, exe_name=None): cfiles = [self.c_source_filename] + self.extrafiles + if exe_name is not None: + exe_name = targetdir.join(exe_name) mk = self.translator.platform.gen_makefile( cfiles, self.eci, path=targetdir, exe_name=exe_name, Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/primitive.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/primitive.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/primitive.py Fri Jun 18 20:55:39 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ CompositeOffset, ArrayLengthOffset, \ - GCHeaderOffset, GCREF + GCHeaderOffset, GCREF, AddressAsInt from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation from pypy.translator.c.support import cdecl, barebonearray @@ -61,6 +61,8 @@ name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) + elif isinstance(value, AddressAsInt): + return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r"%value) if value is None: Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/src/address.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/src/address.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/src/address.h Fri Jun 18 20:55:39 2010 @@ -16,5 +16,5 @@ #define OP_ADR_LT(x,y,r) r = ((x) < (y)) #define OP_ADR_GE(x,y,r) r = ((x) >= (y)) -#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x) -#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) +#define OP_CAST_ADR_TO_INT(x, mode, r) r = ((long)x) +#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/src/commondefs.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/src/commondefs.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/src/commondefs.h Fri Jun 18 20:55:39 2010 @@ -82,5 +82,7 @@ #define Py_HUGE_VAL HUGE_VAL #ifdef _WIN32 +#ifndef MS_WINDOWS # define MS_WINDOWS /* a synonym */ #endif +#endif Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/src/int.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/src/int.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/src/int.h Fri Jun 18 20:55:39 2010 @@ -47,6 +47,14 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) +/* Implement INT_BETWEEN by optimizing for the common case where a and c + are constants (the 2nd subtraction below is then constant-folded), or + for the case of a == 0 (both subtractions are then constant-folded). + Note that the following line only works if a <= c in the first place, + which we assume is true. */ +#define OP_INT_BETWEEN(a,b,c,r) r = (((unsigned long)b - (unsigned long)a) \ + < ((unsigned long)c - (unsigned long)a)) + /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/src/mem.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/src/mem.h Fri Jun 18 20:55:39 2010 @@ -6,8 +6,7 @@ extern char __gcmapstart; extern char __gcmapend; extern char __gccallshapes; -extern void *__gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); #define __gcnoreorderhack __gcmapend /* The following pseudo-instruction is used by --gcrootfinder=asmgcc @@ -47,15 +46,13 @@ i == 0 ? (void*)&__gcmapstart : \ i == 1 ? (void*)&__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #else extern void* __gcmapstart; extern void* __gcmapend; extern char* __gccallshapes; -extern void* __gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); /* With the msvc Microsoft Compiler, the optimizer seems free to move any code (even asm) that involves local memory (registers and stack). @@ -82,7 +79,6 @@ i == 0 ? (void*)__gcmapstart : \ i == 1 ? (void*)__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #endif Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/src/stack.h ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/src/stack.h (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/src/stack.h Fri Jun 18 20:55:39 2010 @@ -3,7 +3,7 @@ /*** C header subsection: stack operations ***/ #ifndef MAX_STACK_SIZE -# define MAX_STACK_SIZE (1 << 19) +# define MAX_STACK_SIZE (3 << 18) /* 768 kb */ #endif /* This include must be done in any case to initialise Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_extfunc.py Fri Jun 18 20:55:39 2010 @@ -221,13 +221,6 @@ res = f1() assert res == os.getcwd() -def test_strerror(): - def does_stuff(): - return os.strerror(2) - f1 = compile(does_stuff, []) - res = f1() - assert res == os.strerror(2) - def test_system(): def does_stuff(cmd): return os.system(cmd) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_genc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_genc.py Fri Jun 18 20:55:39 2010 @@ -144,10 +144,8 @@ assert f1() == '\x00' def test_runtime_type_info(): - S = GcStruct('s', ('is_actually_s1', Bool)) - S1 = GcStruct('s1', ('sub', S)) - attachRuntimeTypeInfo(S) - attachRuntimeTypeInfo(S1) + S = GcStruct('s', ('is_actually_s1', Bool), rtti=True) + S1 = GcStruct('s1', ('sub', S), rtti=True) def rtti_S(p): if p.is_actually_s1: return getRuntimeTypeInfo(S1) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_lladdresses.py Fri Jun 18 20:55:39 2010 @@ -193,3 +193,42 @@ fc = compile(f, [int]) res = fc(42) assert res == 0 + +def test_cast_int_to_adr(): + S = lltype.Struct("S", ("x", lltype.Signed)) + s = lltype.malloc(S, immortal=True) + s.x = 42 + integer = cast_adr_to_int(cast_ptr_to_adr(s), mode="symbolic") + def f(n): + if n > 1: + i = integer + else: + i = 123 # nonsense, but never used + print "hello world" # prevent constant-folding + adr = cast_int_to_adr(i) + s = cast_adr_to_ptr(adr, lltype.Ptr(S)) + return s.x + fc = compile(f, [int]) + res = fc(5) + assert res == 42 + +def test_dict_of_addresses(): + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def f(i): + d = {} + d[cast_ptr_to_adr(a)] = 123 + d[cast_ptr_to_adr(b)] = 456 + if i > 5: + key = cast_ptr_to_adr(a) + else: + key = cast_ptr_to_adr(b) + return d[key] + + fc = compile(f, [int]) + res = fc(-77) + assert res == 456 + res = fc(77) + assert res == 123 Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_refcount.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_refcount.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_refcount.py Fri Jun 18 20:55:39 2010 @@ -130,9 +130,8 @@ def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: - S = lltype.GcStruct('S', ('x', lltype.Signed)) + S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_standalone.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_standalone.py Fri Jun 18 20:55:39 2010 @@ -210,6 +210,7 @@ filename = str(udir.join('test_standalone_largefile')) r4800000000 = r_longlong(4800000000L) def entry_point(argv): + assert str(r4800000000 + len(argv)) == '4800000003' fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644) os.lseek(fd, r4800000000, 0) newpos = os.lseek(fd, 0, 1) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_typed.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/c/test/test_typed.py Fri Jun 18 20:55:39 2010 @@ -79,11 +79,6 @@ nested_whiles = self.getcompiled(snippet.nested_whiles, [int, int]) assert nested_whiles(5,3) == '!!!!!' - def test_call_five(self): - call_five = self.getcompiled(snippet.call_five, [int]) - result = call_five() - assert result == [5] - def test_call_unpack_56(self): call_unpack_56 = self.getcompiled(snippet.call_unpack_56, []) result = call_unpack_56() @@ -116,13 +111,6 @@ assert fn(4) == 789 assert fn(5) == 101112 - def test_get_set_del_slice(self): - fn = self.getcompiled(snippet.get_set_del_slice, [list]) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - def test_type_conversion(self): # obfuscated test case specially for typer.insert_link_conversions() def type_conversion(n): Modified: pypy/branch/x86-64-jit-backend/pypy/translator/driver.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/driver.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/driver.py Fri Jun 18 20:55:39 2010 @@ -513,7 +513,12 @@ defines = cbuilder.DEBUG_DEFINES else: defines = {} - c_source_filename = cbuilder.generate_source(database, defines) + if self.exe_name is not None: + exe_name = self.exe_name % self.get_info() + else: + exe_name = None + c_source_filename = cbuilder.generate_source(database, defines, + exe_name=exe_name) self.log.info("written: %s" % (c_source_filename,)) if self.config.translation.dump_static_data_info: from pypy.translator.tool.staticsizereport import dump_static_data_info @@ -530,19 +535,20 @@ newexename = self.exe_name % self.get_info() if '/' not in newexename and '\\' not in newexename: newexename = './' + newexename - return mkexename(py.path.local(newexename)) + return py.path.local(newexename) def create_exe(self): """ Copy the compiled executable into translator/goal """ if self.exe_name is not None: - exename = mkexename(self.c_entryp) - newexename = self.compute_exe_name() + exename = self.c_entryp + newexename = mkexename(self.compute_exe_name()) shutil.copy(str(exename), str(newexename)) if self.cbuilder.shared_library_name is not None: soname = self.cbuilder.shared_library_name newsoname = newexename.new(basename=soname.basename) shutil.copy(str(soname), str(newsoname)) + self.log.info("copied: %s" % (newsoname,)) self.c_entryp = newexename self.log.info("created: %s" % (self.c_entryp,)) Modified: pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpreimportedpypy.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpreimportedpypy.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpreimportedpypy.py Fri Jun 18 20:55:39 2010 @@ -3,7 +3,6 @@ import os, sys sys.setrecursionlimit(17000) -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy Modified: pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/goal/targetpypystandalone.py Fri Jun 18 20:55:39 2010 @@ -2,7 +2,6 @@ import os, sys -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy Modified: pypy/branch/x86-64-jit-backend/pypy/translator/platform/__init__.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/platform/__init__.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/platform/__init__.py Fri Jun 18 20:55:39 2010 @@ -5,6 +5,7 @@ import sys, py, os +from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_log log = py.log.Producer("platform") py.log.setconsumer("platform", ansi_log) @@ -62,9 +63,20 @@ def execute(self, executable, args=None, env=None, compilation_info=None): if env is None: env = os.environ.copy() - if compilation_info is not None: + else: + env = env.copy() + + # On Windows, %SystemRoot% must be present for most programs to start + if (os.name == 'nt' and + "SystemRoot" not in env and + "SystemRoot" in os.environ): + env["SystemRoot"] = os.environ["SystemRoot"] + + # Set LD_LIBRARY_PATH on posix platforms + if os.name == 'posix' and compilation_info is not None: env['LD_LIBRARY_PATH'] = ':'.join( [str(i) for i in compilation_info.library_dirs]) + returncode, stdout, stderr = _run_subprocess(str(executable), args, env) return ExecutionResult(returncode, stdout, stderr) @@ -112,6 +124,18 @@ for line in stderr.splitlines(): log.WARNING(line) + def _make_response_file(self, prefix): + """Creates a temporary file with the specified prefix, + and returns its name""" + # Build unique filename + num = 0 + while 1: + response_file = udir.join('%s%i' % (prefix, num)) + num += 1 + if not response_file.check(): + break + return response_file + def _preprocess_include_dirs(self, include_dirs): return include_dirs @@ -133,9 +157,15 @@ library_dirs = self._libdirs(library_dirs) libraries = self._libs(eci.libraries) link_files = self._linkfiles(eci.link_files) - return (library_dirs + self.link_flags + + export_flags = self._exportsymbols_link_flags(eci) + return (library_dirs + self.link_flags + export_flags + link_files + list(eci.link_extra) + libraries) + def _exportsymbols_link_flags(self, eci): + if eci.export_symbols: + raise ValueError("This platform does not support export symbols") + return [] + def _finish_linking(self, ofiles, eci, outputfilename, standalone): if outputfilename is None: outputfilename = ofiles[0].purebasename Modified: pypy/branch/x86-64-jit-backend/pypy/translator/platform/darwin.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/platform/darwin.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/platform/darwin.py Fri Jun 18 20:55:39 2010 @@ -56,6 +56,17 @@ include_dirs = self._includedirs(eci.include_dirs) return (args + frameworks + include_dirs) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("_%s\n" % (sym,)) + f.close() + return ["-Wl,-exported_symbols_list,%s" % (response_file,)] + class Darwin_i386(Darwin): name = "darwin_i386" link_flags = ['-arch', 'i386', '-mmacosx-version-min=10.4'] Modified: pypy/branch/x86-64-jit-backend/pypy/translator/platform/posix.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/platform/posix.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/platform/posix.py Fri Jun 18 20:55:39 2010 @@ -37,9 +37,21 @@ return oname def _link_args_from_eci(self, eci, standalone): - eci = eci.convert_exportsymbols_to_file() return Platform._link_args_from_eci(self, eci, standalone) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + f.write("{\n") + for sym in eci.export_symbols: + f.write("%s;\n" % (sym,)) + f.write("};") + f.close() + return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] + def _link(self, cc, ofiles, link_args, standalone, exe_name): args = [str(ofile) for ofile in ofiles] + link_args args += ['-o', str(exe_name)] @@ -61,7 +73,6 @@ def gen_makefile(self, cfiles, eci, exe_name=None, path=None, shared=False): - eci = eci.convert_exportsymbols_to_file() cfiles = [py.path.local(f) for f in cfiles] cfiles += [py.path.local(f) for f in eci.separate_module_files] @@ -72,11 +83,15 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + linkflags += self._exportsymbols_link_flags(eci) + if shared: libname = exe_name.new(ext='').basename target_name = 'lib' + exe_name.new(ext=self.so_ext).basename @@ -133,6 +148,7 @@ if shared: m.definition('SHARED_IMPORT_LIB', libname), + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo "' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' Modified: pypy/branch/x86-64-jit-backend/pypy/translator/platform/test/test_platform.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/platform/test/test_platform.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/platform/test/test_platform.py Fri Jun 18 20:55:39 2010 @@ -113,7 +113,7 @@ def test_environment_inheritance(self): # make sure that environment is inherited cmd = 'import os; print os.environ["_SOME_VARIABLE_%d"]' - res = self.platform.execute('python', ['-c', cmd % 1], + res = self.platform.execute(sys.executable, ['-c', cmd % 1], env={'_SOME_VARIABLE_1':'xyz'}) assert 'xyz' in res.out os.environ['_SOME_VARIABLE_2'] = 'zyz' Modified: pypy/branch/x86-64-jit-backend/pypy/translator/platform/windows.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/platform/windows.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/platform/windows.py Fri Jun 18 20:55:39 2010 @@ -139,8 +139,18 @@ def _link_args_from_eci(self, eci, standalone): # Windows needs to resolve all symbols even for DLLs - args = super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) - return args + ['/EXPORT:%s' % symbol for symbol in eci.export_symbols] + return super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) + + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("exported_symbols_") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("/EXPORT:%s\n" % (sym,)) + f.close() + return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): oname = cfile.new(ext='obj') @@ -179,7 +189,7 @@ # Microsoft compilers write compilation errors to stdout stderr = stdout + stderr errorfile = outname.new(ext='errors') - errorfile.write(stderr) + errorfile.write(stderr, mode='wb') stderrlines = stderr.splitlines() for line in stderrlines: log.ERROR(line) @@ -198,18 +208,22 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) m = NMakefile(path) m.exe_name = exe_name m.eci = eci - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + [ '/EXPORT:$(PYPY_MAIN_FUNCTION)'] + linkflags += self._exportsymbols_link_flags(eci) if shared: - so_name = exe_name.new(ext=self.so_ext) + so_name = exe_name.new(purebasename='lib' + exe_name.purebasename, + ext=self.so_ext) target_name = so_name.basename else: target_name = exe_name.basename @@ -243,6 +257,7 @@ ('LDFLAGSEXTRA', list(eci.link_extra)), ('CC', self.cc), ('CC_LINK', self.link), + ('LINKFILES', eci.link_files), ('MASM', self.masm), ] @@ -262,19 +277,22 @@ '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS)') else: m.rule('$(TARGET)', '$(OBJECTS)', - ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) if shared: - m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename), + m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename) + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo ' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' 'int main(int argc, char* argv[]) ' '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@') m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'], - '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@') + ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFESTFILE:$*.manifest', + 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', + ]) return m @@ -319,6 +337,7 @@ shared_only = [] cflags = ['-O3'] link_flags = [] + exe_ext = 'exe' so_ext = 'dll' def __init__(self, cc=None): Modified: pypy/branch/x86-64-jit-backend/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/tool/cbuild.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/tool/cbuild.py Fri Jun 18 20:55:39 2010 @@ -260,34 +260,6 @@ d['separate_module_files'] += tuple(files) return ExternalCompilationInfo(**d) - def convert_exportsymbols_to_file(self): - if not self.export_symbols: - return self - num = 0 - while 1: - file_name = udir.join('dynamic-symbols-%i' % num) - num += 1 - if not file_name.check(): - break - - # XXX this logic should be moved to translator/platform/*.py - d = self._copy_attributes() - f = file_name.open("w") - if host.name.startswith('darwin'): - for sym in self.export_symbols: - f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) - else: - f.write("{\n") - for sym in self.export_symbols: - f.write("%s;\n" % (sym,)) - f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) - f.close() - d['export_symbols'] = () - return ExternalCompilationInfo(**d) - - def get_module_files(self): d = self._copy_attributes() files = d['separate_module_files'] Modified: pypy/branch/x86-64-jit-backend/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/tool/make_dot.py Fri Jun 18 20:55:39 2010 @@ -152,7 +152,7 @@ shape = "octagon" if block.exitswitch is not None: - lines.append("exitswitch: %s" % block.exitswitch) + lines.append("exitswitch: %s" % (block.exitswitch,)) iargs = " ".join(map(repr, block.inputargs)) if self.VERBOSE: Modified: pypy/branch/x86-64-jit-backend/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/tool/test/test_cbuild.py Fri Jun 18 20:55:39 2010 @@ -71,17 +71,6 @@ e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e - def test_convert_sources_to_c_files(self): - eci = ExternalCompilationInfo( - export_symbols=("foo", ) - ) - neweci = eci.convert_exportsymbols_to_file() - le = neweci.link_extra[-1] - assert "foo;" in file(le.rsplit("=", 1)[1]).read() - e = ExternalCompilationInfo() - assert e.convert_exportsymbols_to_file() is e - - def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' Modified: pypy/branch/x86-64-jit-backend/pypy/translator/translator.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/translator/translator.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/translator/translator.py Fri Jun 18 20:55:39 2010 @@ -7,7 +7,6 @@ import autopath, os, sys, types, copy from pypy.translator import simplify -from pypy.objspace.flow.objspace import FlowObjSpace from pypy.objspace.flow.model import FunctionGraph, checkgraph, Block from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func @@ -67,6 +66,7 @@ else: if self.config.translation.verbose: log.start(nice_repr_for_func(func)) + from pypy.objspace.flow.objspace import FlowObjSpace space = FlowObjSpace(self.flowconfig) if self.annotator: # ZZZ From fijal at codespeak.net Fri Jun 18 20:59:22 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 20:59:22 +0200 (CEST) Subject: [pypy-svn] r75457 - pypy/build/bot2/pypybuildbot Message-ID: <20100618185922.92E14282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 20:59:19 2010 New Revision: 75457 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Fix overzelaus deindent Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri Jun 18 20:59:19 2010 @@ -129,7 +129,7 @@ logfiles={'pytestLog': 'cpython.log'})) if pypyjit: - upload nightly build, if we're running jit tests + # upload nightly build, if we're running jit tests self.addStep(ShellCmd( description="pypyjit tests", command=["python", "pypy/test_all.py", From fijal at codespeak.net Fri Jun 18 21:05:21 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 21:05:21 +0200 (CEST) Subject: [pypy-svn] r75458 - in pypy/release/1.3.x: . pypy/tool/release pypy/tool/release/test Message-ID: <20100618190521.4C2F1282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 21:04:55 2010 New Revision: 75458 Removed: pypy/release/1.3.x/pypy/tool/release/pack.py pypy/release/1.3.x/pypy/tool/release/test/test_pack.py Modified: pypy/release/1.3.x/ (props changed) Log: Merge from trunk From fijal at codespeak.net Fri Jun 18 21:10:43 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 21:10:43 +0200 (CEST) Subject: [pypy-svn] r75459 - in pypy/release/1.3.x/pypy/tool: . release release/test test Message-ID: <20100618191043.8E84C282B9C@codespeak.net> Author: fijal Date: Fri Jun 18 21:10:24 2010 New Revision: 75459 Added: pypy/release/1.3.x/pypy/tool/release/package.py (props changed) - copied unchanged from r75458, pypy/trunk/pypy/tool/release/package.py pypy/release/1.3.x/pypy/tool/release/test/test_package.py (props changed) - copied unchanged from r75458, pypy/trunk/pypy/tool/release/test/test_package.py Removed: pypy/release/1.3.x/pypy/tool/package.py pypy/release/1.3.x/pypy/tool/test/test_package.py Log: Ugh. Merge by hand correct places of package.py. I hope it won't change from now on. From fijal at codespeak.net Fri Jun 18 21:11:00 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jun 2010 21:11:00 +0200 (CEST) Subject: [pypy-svn] r75460 - pypy/trunk/pypy/tool/release Message-ID: <20100618191100.45715282BFA@codespeak.net> Author: fijal Date: Fri Jun 18 21:10:57 2010 New Revision: 75460 Modified: pypy/trunk/pypy/tool/release/force-builds.py Log: Disable own-macosx for the release Modified: pypy/trunk/pypy/tool/release/force-builds.py ============================================================================== --- pypy/trunk/pypy/tool/release/force-builds.py (original) +++ pypy/trunk/pypy/tool/release/force-builds.py Fri Jun 18 21:10:57 2010 @@ -19,7 +19,7 @@ BUILDERS = [ 'own-linux-x86-32', 'own-linux-x86-64', - 'own-macosx-x86-32', +# 'own-macosx-x86-32', 'pypy-c-app-level-linux-x86-32', 'pypy-c-app-level-linux-64', 'pypy-c-stackless-app-level-linux-x86-32', From jcreigh at codespeak.net Fri Jun 18 23:09:05 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Fri, 18 Jun 2010 23:09:05 +0200 (CEST) Subject: [pypy-svn] r75461 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100618210905.863E1282B9C@codespeak.net> Author: jcreigh Date: Fri Jun 18 23:09:03 2010 New Revision: 75461 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: fix use of FSTP Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Fri Jun 18 23:09:03 2010 @@ -1563,7 +1563,7 @@ self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: - mc.FSTP(result_loc) + mc.FSTP_b(result_loc.value) #else: result_loc is already either eax or None, checked below mc.JMP_l8(0) # jump to done, patched later jmp_location = mc.get_relative_pos() From cfbolz at codespeak.net Fri Jun 18 23:32:13 2010 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 18 Jun 2010 23:32:13 +0200 (CEST) Subject: [pypy-svn] r75462 - pypy/trunk/pypy/jit/metainterp Message-ID: <20100618213213.AA817282B9C@codespeak.net> Author: cfbolz Date: Fri Jun 18 23:32:11 2010 New Revision: 75462 Modified: pypy/trunk/pypy/jit/metainterp/viewnode.py Log: fix. admittedly this has no tests Modified: pypy/trunk/pypy/jit/metainterp/viewnode.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/viewnode.py (original) +++ pypy/trunk/pypy/jit/metainterp/viewnode.py Fri Jun 18 23:32:11 2010 @@ -55,7 +55,7 @@ if isinstance(self.knownclsbox.value, int): name += str(self.knownclsbox.value) else: - name += str(self.knownclsbox.value.ptr).rpartition("_vtable")[0].rpartition('.')[2] + name += str(self.knownclsbox.value.adr.ptr).rpartition("_vtable")[0].rpartition('.')[2] elif self.structdescr: name = "Struct " + str(self.structdescr) elif self.arraydescr: From cfbolz at codespeak.net Fri Jun 18 23:32:31 2010 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 18 Jun 2010 23:32:31 +0200 (CEST) Subject: [pypy-svn] r75463 - in pypy/trunk/pypy/jit/metainterp: . test Message-ID: <20100618213231.2B6AB282B9C@codespeak.net> Author: cfbolz Date: Fri Jun 18 23:32:29 2010 New Revision: 75463 Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py pypy/trunk/pypy/jit/metainterp/test/test_tl.py Log: a small optimization: get rid of int_is_true(i0) if i0 is a bool. Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py Fri Jun 18 23:32:29 2010 @@ -554,7 +554,7 @@ elif op.can_raise(): self.exception_might_have_happened = True elif op.returns_bool_result(): - self.bool_boxes[op.result] = None + self.bool_boxes[self.getvalue(op.result)] = None self.newoperations.append(op) def store_final_boxes_in_guard(self, op): @@ -568,7 +568,7 @@ descr.store_final_boxes(op, newboxes) # if op.opnum == rop.GUARD_VALUE: - if op.args[0] in self.bool_boxes: + if self.getvalue(op.args[0]) in self.bool_boxes: # Hack: turn guard_value(bool) into guard_true/guard_false. # This is done after the operation is emitted, to let # store_final_boxes_in_guard set the guard_opnum field @@ -746,6 +746,9 @@ self.optimize_default(op) def optimize_INT_IS_TRUE(self, op): + if self.getvalue(op.args[0]) in self.bool_boxes: + self.make_equal_to(op.result, self.getvalue(op.args[0])) + return self._optimize_nullness(op, op.args[0], True) def optimize_INT_IS_ZERO(self, op): Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Fri Jun 18 23:32:29 2010 @@ -597,6 +597,25 @@ """ self.optimize_loop(ops, 'Not', ops) + def test_int_is_true_of_bool(self): + ops = """ + [i0, i1] + i2 = int_gt(i0, i1) + i3 = int_is_true(i2) + i4 = int_is_true(i3) + guard_value(i4, 0) [i0, i1] + jump(i0, i1) + """ + expected = """ + [i0, i1] + i2 = int_gt(i0, i1) + guard_false(i2) [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, 'Not, Not', expected) + + + def test_p123_simple(self): ops = """ Modified: pypy/trunk/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_tl.py Fri Jun 18 23:32:29 2010 @@ -74,8 +74,7 @@ backendopt=True) assert res == 5040 self.check_loops({'int_mul':1, 'jump':1, - 'int_sub':1, 'int_is_true':1, 'int_le':1, - 'guard_false':1}) + 'int_sub':1, 'int_le':1, 'guard_false':1}) def test_tl_2(self): main = self._get_main() @@ -83,7 +82,7 @@ backendopt=True) assert res == main(1, 10) self.check_loops({'int_sub':1, 'int_le':1, - 'int_is_true':1, 'guard_false':1, 'jump':1}) + 'guard_false':1, 'jump':1}) def test_tl_call(self, listops=True, policy=None): from pypy.jit.tl.tl import interp From arigo at codespeak.net Sat Jun 19 16:13:49 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jun 2010 16:13:49 +0200 (CEST) Subject: [pypy-svn] r75470 - pypy/trunk/pypy/translator/c Message-ID: <20100619141349.CC2FB282BD4@codespeak.net> Author: arigo Date: Sat Jun 19 16:13:47 2010 New Revision: 75470 Modified: pypy/trunk/pypy/translator/c/genc.py Log: Fix for test_profopt_mac_osx_bug. Modified: pypy/trunk/pypy/translator/c/genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/genc.py (original) +++ pypy/trunk/pypy/translator/c/genc.py Sat Jun 19 16:13:47 2010 @@ -33,7 +33,7 @@ def first(self): platform = self.compiler.platform - if platform.name == 'darwin': + if platform.name.startswith('darwin'): # XXX incredible hack for darwin cfiles = self.compiler.cfiles STR = '/*--no-profiling-for-this-file!--*/' From arigo at codespeak.net Sat Jun 19 17:22:06 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jun 2010 17:22:06 +0200 (CEST) Subject: [pypy-svn] r75472 - pypy/trunk/pypy/rpython/module Message-ID: <20100619152206.431EC282BDC@codespeak.net> Author: arigo Date: Sat Jun 19 17:22:04 2010 New Revision: 75472 Modified: pypy/trunk/pypy/rpython/module/ll_time.py Log: Give up using clock() directly. It's a mess on OS/X because depending on the includes we get a version that returns either milliseconds or microseconds, and a different CLOCKS_PER_SEC. But the latter is hard-coded in the C source, while the version of clock() that will be used depends on how the C source is linked. Instead, use getrusage() which returns numbers as a pair of nice 'struct timeval'. Modified: pypy/trunk/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_time.py (original) +++ pypy/trunk/pypy/rpython/module/ll_time.py Sat Jun 19 17:22:04 2010 @@ -17,24 +17,28 @@ STRUCT_TIMEB = 'struct __timeb64' includes = ['winsock2.h', 'windows.h', TIME_H, 'sys/types.h', 'sys/timeb.h'] + need_rusage = False else: TIME_H = 'sys/time.h' FTIME = 'ftime' STRUCT_TIMEB = 'struct timeb' includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', - 'sys/types.h', 'unistd.h', 'sys/timeb.h'] + 'sys/types.h', 'unistd.h', 'sys/timeb.h', + 'sys/resource.h'] + need_rusage = True class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=includes ) - CLOCK_T = platform.SimpleType('clock_t', rffi.INT) TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), ('tv_usec', rffi.INT)]) HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') HAVE_FTIME = platform.Has(FTIME) - + if need_rusage: + RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL), + ('ru_stime', TIMEVAL)]) if sys.platform == 'freebsd7': libraries = ['compat'] @@ -49,21 +53,20 @@ TIMEB = platform.Struct(STRUCT_TIMEB, [('time', rffi.INT), ('millitm', rffi.INT)]) -constant_names = ['CLOCKS_PER_SEC', 'CLK_TCK', 'EINTR'] +constant_names = ['RUSAGE_SELF', 'EINTR'] for const in constant_names: setattr(CConfig, const, platform.DefinedConstantInteger(const)) defs_names = ['GETTIMEOFDAY_NO_TZ'] for const in defs_names: setattr(CConfig, const, platform.Defined(const)) +def decode_timeval(t): + return (float(rffi.cast(lltype.Signed, t.c_tv_sec)) + + float(rffi.cast(lltype.Signed, t.c_tv_usec)) * 0.000001) + class RegisterTime(BaseLazyRegistering): def __init__(self): self.configure(CConfig) - if self.CLOCKS_PER_SEC is None: - if self.CLK_TCK is None: - self.CLOCKS_PER_SEC = 1000000 - else: - self.CLOCKS_PER_SEC = self.CLK_TCK self.TIMEVALP = lltype.Ptr(self.TIMEVAL) @registering(time.time) @@ -109,10 +112,7 @@ errcode = c_gettimeofday(t, void) if rffi.cast(rffi.LONG, errcode) == 0: - result = float(rffi.cast(lltype.Signed, t.c_tv_sec)) \ - + float(rffi.cast(lltype.Signed, t.c_tv_usec)) \ - * 0.000001 - + result = decode_timeval(t) lltype.free(t, flavor='raw') if result != -1: return result @@ -129,8 +129,6 @@ @registering(time.clock) def register_time_clock(self): - c_clock = self.llexternal('clock', [], self.CLOCK_T, - threadsafe=False) if sys.platform == 'win32': # hacking to avoid LARGE_INTEGER which is a union... A = lltype.FixedSizeArray(lltype.SignedLongLong, 1) @@ -157,9 +155,19 @@ lltype.free(a, flavor='raw') return float(diff) / state.divisor else: + RUSAGE = self.RUSAGE + RUSAGE_SELF = self.RUSAGE_SELF or 0 + c_getrusage = self.llexternal('getrusage', + [rffi.INT, lltype.Ptr(RUSAGE)], + lltype.Void, + threadsafe=False) def time_clock_llimpl(): - result = c_clock() - return float(result) / self.CLOCKS_PER_SEC + a = lltype.malloc(RUSAGE, flavor='raw') + c_getrusage(RUSAGE_SELF, a) + result = (decode_timeval(a.c_ru_utime) + + decode_timeval(a.c_ru_stime)) + lltype.free(a, flavor='raw') + return result return extdef([], float, llimpl=time_clock_llimpl, export_name='ll_time.ll_time_clock') From arigo at codespeak.net Sat Jun 19 17:28:32 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jun 2010 17:28:32 +0200 (CEST) Subject: [pypy-svn] r75473 - in pypy/trunk/pypy/rpython: . module Message-ID: <20100619152832.97C7A282BDC@codespeak.net> Author: arigo Date: Sat Jun 19 17:28:31 2010 New Revision: 75473 Modified: pypy/trunk/pypy/rpython/extfunc.py pypy/trunk/pypy/rpython/module/ll_time.py Log: Fixes. Modified: pypy/trunk/pypy/rpython/extfunc.py ============================================================================== --- pypy/trunk/pypy/rpython/extfunc.py (original) +++ pypy/trunk/pypy/rpython/extfunc.py Sat Jun 19 17:28:31 2010 @@ -94,6 +94,7 @@ class BaseLazyRegistering(object): __metaclass__ = LazyRegisteringMeta + compilation_info = None def configure(self, CConfig): classes_seen = self.__dict__.setdefault('__classes_seen', {}) @@ -101,7 +102,11 @@ return from pypy.rpython.tool import rffi_platform as platform # copy some stuff - self.compilation_info = CConfig._compilation_info_ + if self.compilation_info is None: + self.compilation_info = CConfig._compilation_info_ + else: + self.compilation_info = self.compilation_info.merge( + CConfig._compilation_info_) self.__dict__.update(platform.configure(CConfig)) classes_seen[CConfig] = True Modified: pypy/trunk/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_time.py (original) +++ pypy/trunk/pypy/rpython/module/ll_time.py Sat Jun 19 17:28:31 2010 @@ -24,7 +24,7 @@ STRUCT_TIMEB = 'struct timeb' includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', 'sys/types.h', 'unistd.h', 'sys/timeb.h', - 'sys/resource.h'] + 'sys/time.h', 'sys/resource.h'] need_rusage = True From arigo at codespeak.net Sat Jun 19 17:46:20 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jun 2010 17:46:20 +0200 (CEST) Subject: [pypy-svn] r75474 - pypy/trunk/pypy/translator/sandbox/test Message-ID: <20100619154620.CD6A9282BDC@codespeak.net> Author: arigo Date: Sat Jun 19 17:46:19 2010 New Revision: 75474 Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py Log: Fix test for Mac OS/X. Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py Sat Jun 19 17:46:19 2010 @@ -145,7 +145,9 @@ g = pipe.stdin f = pipe.stdout expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GENERATIONGC_NURSERY",), None) - expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), OSError(5232, "xyz")) + if sys.platform == 'linux2': # on Mac, uses another (sandboxsafe) approach + expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), + OSError(5232, "xyz")) g.close() tail = f.read() f.close() From fijal at codespeak.net Sun Jun 20 07:38:30 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jun 2010 07:38:30 +0200 (CEST) Subject: [pypy-svn] r75475 - pypy/trunk/pypy/tool/release Message-ID: <20100620053830.49836282B9E@codespeak.net> Author: fijal Date: Sun Jun 20 07:38:27 2010 New Revision: 75475 Modified: pypy/trunk/pypy/tool/release/package.py Log: Package includes together with everything else Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Sun Jun 20 07:38:27 2010 @@ -34,8 +34,12 @@ def package(basedir, name='pypy-nightly', rename_pypy_c='pypy-c', copy_to_dir = None, override_pypy_c = None): basedir = py.path.local(basedir) + if sys.platform == 'win32': + basename = 'pypy-c.exe' + else: + basename = 'pypy-c' if override_pypy_c is None: - pypy_c = basedir.join('pypy', 'translator', 'goal', 'pypy-c') + pypy_c = basedir.join('pypy', 'translator', 'goal', basename) else: pypy_c = py.path.local(override_pypy_c) if not pypy_c.check(): @@ -53,6 +57,13 @@ ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) + pypydir.ensure('include', dir=True) + # we want to put there all *.h from module/cpyext/include + # and from pypy/_interfaces + for n in basedir.join('pypy', 'module', 'cpyext', 'include').listdir('*.h'): + shutil.copy(str(n), str(pypydir.join('include'))) + for n in basedir.join('pypy', '_interfaces').listdir('*.h'): + shutil.copy(str(n), str(pypydir.join('include'))) pypydir.ensure('bin', dir=True) archive_pypy_c = pypydir.join('bin', rename_pypy_c) shutil.copy(str(pypy_c), str(archive_pypy_c)) From fijal at codespeak.net Sun Jun 20 07:39:43 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jun 2010 07:39:43 +0200 (CEST) Subject: [pypy-svn] r75476 - pypy/trunk/lib-python/modified-2.5.2/distutils Message-ID: <20100620053943.D4CBE282B9E@codespeak.net> Author: fijal Date: Sun Jun 20 07:39:42 2010 New Revision: 75476 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Log: Look also into pypy_prefix/include, hopefully a short living hack. Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Sun Jun 20 07:39:42 2010 @@ -13,6 +13,9 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j + cand = j(sys.pypy_prefix, 'include') + if os.path.exists(cand): + return cand if plat_specific: return j(sys.pypy_prefix, "pypy", "_interfaces") return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') From fijal at codespeak.net Sun Jun 20 07:43:42 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jun 2010 07:43:42 +0200 (CEST) Subject: [pypy-svn] r75477 - in pypy/release/1.3.x: . lib-python/modified-2.5.2/distutils pypy/tool/release pypy/tool/release/test Message-ID: <20100620054342.5E571282B9E@codespeak.net> Author: fijal Date: Sun Jun 20 07:43:40 2010 New Revision: 75477 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/release/1.3.x/pypy/tool/release/package.py (contents, props changed) pypy/release/1.3.x/pypy/tool/release/test/test_package.py (props changed) Log: Merge r75475 and r75476 from trunk Modified: pypy/release/1.3.x/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/release/1.3.x/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/release/1.3.x/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Sun Jun 20 07:43:40 2010 @@ -13,6 +13,9 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j + cand = j(sys.pypy_prefix, 'include') + if os.path.exists(cand): + return cand if plat_specific: return j(sys.pypy_prefix, "pypy", "_interfaces") return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') Modified: pypy/release/1.3.x/pypy/tool/release/package.py ============================================================================== --- pypy/release/1.3.x/pypy/tool/release/package.py (original) +++ pypy/release/1.3.x/pypy/tool/release/package.py Sun Jun 20 07:43:40 2010 @@ -34,8 +34,12 @@ def package(basedir, name='pypy-nightly', rename_pypy_c='pypy-c', copy_to_dir = None, override_pypy_c = None): basedir = py.path.local(basedir) + if sys.platform == 'win32': + basename = 'pypy-c.exe' + else: + basename = 'pypy-c' if override_pypy_c is None: - pypy_c = basedir.join('pypy', 'translator', 'goal', 'pypy-c') + pypy_c = basedir.join('pypy', 'translator', 'goal', basename) else: pypy_c = py.path.local(override_pypy_c) if not pypy_c.check(): @@ -53,6 +57,13 @@ ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) + pypydir.ensure('include', dir=True) + # we want to put there all *.h from module/cpyext/include + # and from pypy/_interfaces + for n in basedir.join('pypy', 'module', 'cpyext', 'include').listdir('*.h'): + shutil.copy(str(n), str(pypydir.join('include'))) + for n in basedir.join('pypy', '_interfaces').listdir('*.h'): + shutil.copy(str(n), str(pypydir.join('include'))) pypydir.ensure('bin', dir=True) archive_pypy_c = pypydir.join('bin', rename_pypy_c) shutil.copy(str(pypy_c), str(archive_pypy_c)) From arigo at codespeak.net Sun Jun 20 11:27:43 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 20 Jun 2010 11:27:43 +0200 (CEST) Subject: [pypy-svn] r75478 - pypy/trunk/pypy/lib Message-ID: <20100620092743.109F8282B9E@codespeak.net> Author: arigo Date: Sun Jun 20 11:27:42 2010 New Revision: 75478 Modified: pypy/trunk/pypy/lib/datetime.py Log: Typo (thanks Ademan). Modified: pypy/trunk/pypy/lib/datetime.py ============================================================================== --- pypy/trunk/pypy/lib/datetime.py (original) +++ pypy/trunk/pypy/lib/datetime.py Sun Jun 20 11:27:42 2010 @@ -1524,7 +1524,7 @@ # Convert self to UTC, and attach the new time zone object. myoffset = self.utcoffset() if myoffset is None: - raise ValuError("astimezone() requires an aware datetime") + raise ValueError("astimezone() requires an aware datetime") utc = (self - myoffset).replace(tzinfo=tz) # Convert from UTC to tz's local time. From benjamin at codespeak.net Sun Jun 20 18:38:55 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 20 Jun 2010 18:38:55 +0200 (CEST) Subject: [pypy-svn] r75479 - in pypy/branch/fast-forward: . dotviewer lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command lib-python/modified-2.5.2/distutils/tests py py/_cmdline py/_code py/_compat py/_io py/_log py/_path py/_path/gateway py/_plugin py/_process py/_test pypy/annotation pypy/annotation/test pypy/doc pypy/doc/play1 pypy/interpreter/test pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/llgraph/test pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/test pypy/jit/tl pypy/jit/tl/spli pypy/jit/tl/tinyframe pypy/jit/tl/tinyframe/test pypy/jit/tl/tla pypy/jit/tool pypy/jit/tool/test pypy/lib pypy/lib/app_test pypy/lib/app_test/ctypes_tests pypy/lib/test2 pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/_codecs pypy/module/_codecs/test pypy/module/_file/test pypy/module/_rawffi pypy/module/_rawffi/test pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/patches pypy/module/cpyext/test pypy/module/imp/test pypy/module/itertools/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/sys pypy/module/sys/test pypy/module/zipimport pypy/module/zipimport/test pypy/objspace/flow pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/parsing/test pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory/gc pypy/rpython/memory/gctransform pypy/rpython/memory/gctransform/test pypy/rpython/memory/test pypy/rpython/module pypy/rpython/numpy/test pypy/rpython/ootypesystem pypy/rpython/ootypesystem/test pypy/rpython/test pypy/rpython/tool pypy/tool pypy/tool/algo pypy/tool/algo/test pypy/tool/release pypy/tool/test pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/platform pypy/translator/platform/test pypy/translator/sandbox/test pypy/translator/tool pypy/translator/tool/test Message-ID: <20100620163855.BD9E2282B9E@codespeak.net> Author: benjamin Date: Sun Jun 20 18:38:42 2010 New Revision: 75479 Added: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py - copied unchanged from r75478, pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py pypy/branch/fast-forward/pypy/doc/release-1.3.0.txt - copied unchanged from r75478, pypy/trunk/pypy/doc/release-1.3.0.txt pypy/branch/fast-forward/pypy/jit/codewriter/ (props changed) - copied from r75478, pypy/trunk/pypy/jit/codewriter/ pypy/branch/fast-forward/pypy/jit/metainterp/blackhole.py - copied unchanged from r75478, pypy/trunk/pypy/jit/metainterp/blackhole.py pypy/branch/fast-forward/pypy/jit/metainterp/jitexc.py - copied unchanged from r75478, pypy/trunk/pypy/jit/metainterp/jitexc.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_immutable.py - copied unchanged from r75478, pypy/trunk/pypy/jit/metainterp/test/test_immutable.py pypy/branch/fast-forward/pypy/lib/test2/test_dbm_extra.py - copied unchanged from r75478, pypy/trunk/pypy/lib/test2/test_dbm_extra.py pypy/branch/fast-forward/pypy/module/cpyext/cdatetime.py - copied unchanged from r75478, pypy/trunk/pypy/module/cpyext/cdatetime.py pypy/branch/fast-forward/pypy/module/cpyext/include/modsupport.inl - copied unchanged from r75478, pypy/trunk/pypy/module/cpyext/include/modsupport.inl pypy/branch/fast-forward/pypy/module/cpyext/patches/cx_Oracle.patch - copied unchanged from r75478, pypy/trunk/pypy/module/cpyext/patches/cx_Oracle.patch pypy/branch/fast-forward/pypy/tool/algo/color.py - copied unchanged from r75478, pypy/trunk/pypy/tool/algo/color.py pypy/branch/fast-forward/pypy/tool/algo/test/test_color.py - copied unchanged from r75478, pypy/trunk/pypy/tool/algo/test/test_color.py pypy/branch/fast-forward/pypy/tool/release/ - copied from r75478, pypy/trunk/pypy/tool/release/ Removed: pypy/branch/fast-forward/pypy/doc/play1/ pypy/branch/fast-forward/pypy/jit/metainterp/codewriter.py pypy/branch/fast-forward/pypy/jit/metainterp/dump.py pypy/branch/fast-forward/pypy/jit/metainterp/effectinfo.py pypy/branch/fast-forward/pypy/jit/metainterp/heaptracker.py pypy/branch/fast-forward/pypy/jit/metainterp/policy.py pypy/branch/fast-forward/pypy/jit/metainterp/support.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_codewriter.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_effectinfo.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_support.py pypy/branch/fast-forward/pypy/module/cpyext/datetime.py pypy/branch/fast-forward/pypy/tool/package.py pypy/branch/fast-forward/pypy/tool/test/test_package.py Modified: pypy/branch/fast-forward/ (props changed) pypy/branch/fast-forward/dotviewer/graphparse.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/branch/fast-forward/py/ (props changed) pypy/branch/fast-forward/py/__init__.py (props changed) pypy/branch/fast-forward/py/__metainfo.py (props changed) pypy/branch/fast-forward/py/_builtin.py (props changed) pypy/branch/fast-forward/py/_cmdline/ (props changed) pypy/branch/fast-forward/py/_cmdline/__init__.py (props changed) pypy/branch/fast-forward/py/_cmdline/pycleanup.py (props changed) pypy/branch/fast-forward/py/_cmdline/pyconvert_unittest.py (props changed) pypy/branch/fast-forward/py/_cmdline/pycountloc.py (props changed) pypy/branch/fast-forward/py/_cmdline/pylookup.py (props changed) pypy/branch/fast-forward/py/_cmdline/pysvnwcrevert.py (props changed) pypy/branch/fast-forward/py/_cmdline/pytest.py (props changed) pypy/branch/fast-forward/py/_cmdline/pywhich.py (props changed) pypy/branch/fast-forward/py/_code/ (props changed) pypy/branch/fast-forward/py/_code/__init__.py (props changed) pypy/branch/fast-forward/py/_code/_assertionnew.py (contents, props changed) pypy/branch/fast-forward/py/_code/_assertionold.py (contents, props changed) pypy/branch/fast-forward/py/_code/assertion.py (props changed) pypy/branch/fast-forward/py/_code/code.py (props changed) pypy/branch/fast-forward/py/_code/oldmagic.py (props changed) pypy/branch/fast-forward/py/_code/oldmagic2.py (props changed) pypy/branch/fast-forward/py/_code/source.py (props changed) pypy/branch/fast-forward/py/_compat/ (props changed) pypy/branch/fast-forward/py/_compat/__init__.py (props changed) pypy/branch/fast-forward/py/_compat/dep_doctest.py (props changed) pypy/branch/fast-forward/py/_compat/dep_optparse.py (props changed) pypy/branch/fast-forward/py/_compat/dep_subprocess.py (props changed) pypy/branch/fast-forward/py/_compat/dep_textwrap.py (props changed) pypy/branch/fast-forward/py/_error.py (props changed) pypy/branch/fast-forward/py/_io/ (props changed) pypy/branch/fast-forward/py/_io/__init__.py (props changed) pypy/branch/fast-forward/py/_io/capture.py (props changed) pypy/branch/fast-forward/py/_io/saferepr.py (props changed) pypy/branch/fast-forward/py/_io/terminalwriter.py (props changed) pypy/branch/fast-forward/py/_log/ (props changed) pypy/branch/fast-forward/py/_log/__init__.py (props changed) pypy/branch/fast-forward/py/_log/log.py (props changed) pypy/branch/fast-forward/py/_log/warning.py (props changed) pypy/branch/fast-forward/py/_path/ (props changed) pypy/branch/fast-forward/py/_path/__init__.py (props changed) pypy/branch/fast-forward/py/_path/cacheutil.py (props changed) pypy/branch/fast-forward/py/_path/common.py (props changed) pypy/branch/fast-forward/py/_path/gateway/ (props changed) pypy/branch/fast-forward/py/_path/gateway/__init__.py (props changed) pypy/branch/fast-forward/py/_path/gateway/channeltest.py (props changed) pypy/branch/fast-forward/py/_path/gateway/channeltest2.py (props changed) pypy/branch/fast-forward/py/_path/gateway/remotepath.py (props changed) pypy/branch/fast-forward/py/_path/local.py (props changed) pypy/branch/fast-forward/py/_path/svnurl.py (props changed) pypy/branch/fast-forward/py/_path/svnwc.py (props changed) pypy/branch/fast-forward/py/_plugin/ (props changed) pypy/branch/fast-forward/py/_plugin/__init__.py (props changed) pypy/branch/fast-forward/py/_plugin/hookspec.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest__pytest.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_assertion.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_capture.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_default.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_doctest.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_genscript.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_helpconfig.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_hooklog.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_junitxml.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_mark.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_monkeypatch.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_nose.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_pastebin.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_pdb.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_pylint.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_pytester.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_recwarn.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_restdoc.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_resultlog.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_runner.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_skipping.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_terminal.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_tmpdir.py (props changed) pypy/branch/fast-forward/py/_plugin/pytest_unittest.py (props changed) pypy/branch/fast-forward/py/_plugin/standalonetemplate.py (props changed) pypy/branch/fast-forward/py/_process/ (props changed) pypy/branch/fast-forward/py/_process/__init__.py (props changed) pypy/branch/fast-forward/py/_process/cmdexec.py (contents, props changed) pypy/branch/fast-forward/py/_process/forkedfunc.py (props changed) pypy/branch/fast-forward/py/_process/killproc.py (props changed) pypy/branch/fast-forward/py/_std.py (props changed) pypy/branch/fast-forward/py/_test/ (props changed) pypy/branch/fast-forward/py/_test/__init__.py (props changed) pypy/branch/fast-forward/py/_test/cmdline.py (props changed) pypy/branch/fast-forward/py/_test/collect.py (props changed) pypy/branch/fast-forward/py/_test/config.py (props changed) pypy/branch/fast-forward/py/_test/conftesthandle.py (props changed) pypy/branch/fast-forward/py/_test/funcargs.py (props changed) pypy/branch/fast-forward/py/_test/parseopt.py (props changed) pypy/branch/fast-forward/py/_test/pluginmanager.py (props changed) pypy/branch/fast-forward/py/_test/pycollect.py (props changed) pypy/branch/fast-forward/py/_test/session.py (props changed) pypy/branch/fast-forward/py/_xmlgen.py (props changed) pypy/branch/fast-forward/py/apipkg.py (props changed) pypy/branch/fast-forward/pypy/annotation/builtin.py pypy/branch/fast-forward/pypy/annotation/classdef.py pypy/branch/fast-forward/pypy/annotation/description.py pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py pypy/branch/fast-forward/pypy/annotation/unaryop.py pypy/branch/fast-forward/pypy/doc/how-to-release.txt pypy/branch/fast-forward/pypy/interpreter/test/test_function.py pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py pypy/branch/fast-forward/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/fast-forward/pypy/jit/backend/llsupport/descr.py pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_descr.py pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py pypy/branch/fast-forward/pypy/jit/backend/model.py pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py pypy/branch/fast-forward/pypy/jit/backend/test/test_ll_random.py pypy/branch/fast-forward/pypy/jit/backend/test/test_random.py pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py pypy/branch/fast-forward/pypy/jit/backend/x86/ri386.py pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py pypy/branch/fast-forward/pypy/jit/backend/x86/support.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_basic.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_send.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py pypy/branch/fast-forward/pypy/jit/codewriter/test/ (props changed) pypy/branch/fast-forward/pypy/jit/metainterp/compile.py pypy/branch/fast-forward/pypy/jit/metainterp/executor.py pypy/branch/fast-forward/pypy/jit/metainterp/history.py pypy/branch/fast-forward/pypy/jit/metainterp/jitprof.py pypy/branch/fast-forward/pypy/jit/metainterp/logger.py pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py pypy/branch/fast-forward/pypy/jit/metainterp/optimizeutil.py pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py pypy/branch/fast-forward/pypy/jit/metainterp/resoperation.py pypy/branch/fast-forward/pypy/jit/metainterp/resume.py pypy/branch/fast-forward/pypy/jit/metainterp/simple_optimize.py pypy/branch/fast-forward/pypy/jit/metainterp/specnode.py pypy/branch/fast-forward/pypy/jit/metainterp/test/oparser.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_blackhole.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_exception.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_executor.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_history.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_jitprof.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_loop.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefindnode.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_pyjitpl.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_send.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_slist.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_string.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tl.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tlc.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtual.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualref.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py pypy/branch/fast-forward/pypy/jit/metainterp/test/test_ztranslation.py pypy/branch/fast-forward/pypy/jit/metainterp/typesystem.py pypy/branch/fast-forward/pypy/jit/metainterp/viewnode.py pypy/branch/fast-forward/pypy/jit/metainterp/virtualizable.py pypy/branch/fast-forward/pypy/jit/metainterp/virtualref.py pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py pypy/branch/fast-forward/pypy/jit/tl/tinyframe/ (props changed) pypy/branch/fast-forward/pypy/jit/tl/tinyframe/test/ (props changed) pypy/branch/fast-forward/pypy/jit/tl/tl.py pypy/branch/fast-forward/pypy/jit/tl/tla/targettla.py pypy/branch/fast-forward/pypy/jit/tl/tla/tla.py pypy/branch/fast-forward/pypy/jit/tl/tlc.py pypy/branch/fast-forward/pypy/jit/tl/tlr.py pypy/branch/fast-forward/pypy/jit/tool/jitoutput.py pypy/branch/fast-forward/pypy/jit/tool/test/test_jitoutput.py pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_functions.py pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_unicode.py pypy/branch/fast-forward/pypy/lib/app_test/test_functools.py pypy/branch/fast-forward/pypy/lib/datetime.py pypy/branch/fast-forward/pypy/lib/dbm.py pypy/branch/fast-forward/pypy/module/__builtin__/functional.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_functional.py pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py pypy/branch/fast-forward/pypy/module/_codecs/test/test_codecs.py pypy/branch/fast-forward/pypy/module/_file/test/test_file_extra.py pypy/branch/fast-forward/pypy/module/_rawffi/array.py pypy/branch/fast-forward/pypy/module/_rawffi/structure.py pypy/branch/fast-forward/pypy/module/_rawffi/test/test__rawffi.py pypy/branch/fast-forward/pypy/module/cpyext/TODO pypy/branch/fast-forward/pypy/module/cpyext/__init__.py pypy/branch/fast-forward/pypy/module/cpyext/api.py pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h pypy/branch/fast-forward/pypy/module/cpyext/listobject.py pypy/branch/fast-forward/pypy/module/cpyext/modsupport.py pypy/branch/fast-forward/pypy/module/cpyext/patches/mysqldb.patch (props changed) pypy/branch/fast-forward/pypy/module/cpyext/patches/numpy.patch (props changed) pypy/branch/fast-forward/pypy/module/cpyext/patches/pycairo.patch (props changed) pypy/branch/fast-forward/pypy/module/cpyext/sequence.py pypy/branch/fast-forward/pypy/module/cpyext/state.py pypy/branch/fast-forward/pypy/module/cpyext/stringobject.py pypy/branch/fast-forward/pypy/module/cpyext/stubs.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_unicodeobject.py pypy/branch/fast-forward/pypy/module/cpyext/unicodeobject.py pypy/branch/fast-forward/pypy/module/imp/test/test_app.py pypy/branch/fast-forward/pypy/module/itertools/test/test_itertools.py pypy/branch/fast-forward/pypy/module/pypyjit/policy.py pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py pypy/branch/fast-forward/pypy/module/sys/app.py pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py pypy/branch/fast-forward/pypy/module/zipimport/interp_zipimport.py pypy/branch/fast-forward/pypy/module/zipimport/test/test_undocumented.py pypy/branch/fast-forward/pypy/module/zipimport/test/test_zipimport.py pypy/branch/fast-forward/pypy/objspace/flow/model.py pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py pypy/branch/fast-forward/pypy/objspace/std/dicttype.py pypy/branch/fast-forward/pypy/objspace/std/frame.py pypy/branch/fast-forward/pypy/objspace/std/settype.py pypy/branch/fast-forward/pypy/objspace/std/stringobject.py pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py pypy/branch/fast-forward/pypy/objspace/std/test/test_unicodeobject.py pypy/branch/fast-forward/pypy/objspace/std/transparent.py pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py pypy/branch/fast-forward/pypy/rlib/jit.py pypy/branch/fast-forward/pypy/rlib/parsing/test/test_regexparse.py pypy/branch/fast-forward/pypy/rlib/rgc.py pypy/branch/fast-forward/pypy/rlib/runicode.py pypy/branch/fast-forward/pypy/rlib/test/test_rbigint.py pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py pypy/branch/fast-forward/pypy/rlib/test/test_rmmap.py pypy/branch/fast-forward/pypy/rlib/test/test_rpoll.py pypy/branch/fast-forward/pypy/rlib/test/test_runicode.py pypy/branch/fast-forward/pypy/rpython/extfunc.py pypy/branch/fast-forward/pypy/rpython/llinterp.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/opimpl.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rlist.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py pypy/branch/fast-forward/pypy/rpython/memory/gc/marksweep.py pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_boehm.py pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/branch/fast-forward/pypy/rpython/memory/test/test_lldict.py pypy/branch/fast-forward/pypy/rpython/module/ll_time.py pypy/branch/fast-forward/pypy/rpython/normalizecalls.py pypy/branch/fast-forward/pypy/rpython/numpy/test/test_array.py pypy/branch/fast-forward/pypy/rpython/ootypesystem/ootype.py pypy/branch/fast-forward/pypy/rpython/ootypesystem/rlist.py pypy/branch/fast-forward/pypy/rpython/ootypesystem/rootype.py pypy/branch/fast-forward/pypy/rpython/ootypesystem/test/test_oolist.py pypy/branch/fast-forward/pypy/rpython/raddress.py pypy/branch/fast-forward/pypy/rpython/rbuiltin.py pypy/branch/fast-forward/pypy/rpython/rmodel.py pypy/branch/fast-forward/pypy/rpython/rrange.py pypy/branch/fast-forward/pypy/rpython/test/test_exception.py pypy/branch/fast-forward/pypy/rpython/test/test_llann.py pypy/branch/fast-forward/pypy/rpython/test/test_llinterp.py pypy/branch/fast-forward/pypy/rpython/test/test_rbuiltin.py pypy/branch/fast-forward/pypy/rpython/test/test_rdict.py pypy/branch/fast-forward/pypy/rpython/test/test_rfloat.py pypy/branch/fast-forward/pypy/rpython/test/test_rint.py pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py pypy/branch/fast-forward/pypy/rpython/test/test_rptr.py pypy/branch/fast-forward/pypy/rpython/test/test_rrange.py pypy/branch/fast-forward/pypy/rpython/test/test_rvirtualizable2.py pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py pypy/branch/fast-forward/pypy/tool/gcc_cache.py pypy/branch/fast-forward/pypy/tool/runsubprocess.py pypy/branch/fast-forward/pypy/tool/sourcetools.py pypy/branch/fast-forward/pypy/tool/test/test_runsubprocess.py pypy/branch/fast-forward/pypy/translator/c/funcgen.py pypy/branch/fast-forward/pypy/translator/c/gcc/test/test_asmgcroot.py pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py pypy/branch/fast-forward/pypy/translator/c/genc.py pypy/branch/fast-forward/pypy/translator/c/primitive.py pypy/branch/fast-forward/pypy/translator/c/src/address.h pypy/branch/fast-forward/pypy/translator/c/src/commondefs.h pypy/branch/fast-forward/pypy/translator/c/src/int.h pypy/branch/fast-forward/pypy/translator/c/src/mem.h pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py pypy/branch/fast-forward/pypy/translator/c/test/test_genc.py pypy/branch/fast-forward/pypy/translator/c/test/test_lladdresses.py pypy/branch/fast-forward/pypy/translator/c/test/test_refcount.py pypy/branch/fast-forward/pypy/translator/c/test/test_typed.py pypy/branch/fast-forward/pypy/translator/driver.py pypy/branch/fast-forward/pypy/translator/goal/targetpreimportedpypy.py pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py pypy/branch/fast-forward/pypy/translator/platform/__init__.py pypy/branch/fast-forward/pypy/translator/platform/darwin.py pypy/branch/fast-forward/pypy/translator/platform/posix.py pypy/branch/fast-forward/pypy/translator/platform/test/test_platform.py pypy/branch/fast-forward/pypy/translator/platform/windows.py pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py pypy/branch/fast-forward/pypy/translator/tool/cbuild.py pypy/branch/fast-forward/pypy/translator/tool/make_dot.py pypy/branch/fast-forward/pypy/translator/tool/test/test_cbuild.py pypy/branch/fast-forward/pypy/translator/translator.py Log: merge from trunk Modified: pypy/branch/fast-forward/dotviewer/graphparse.py ============================================================================== --- pypy/branch/fast-forward/dotviewer/graphparse.py (original) +++ pypy/branch/fast-forward/dotviewer/graphparse.py Sun Jun 20 18:38:42 2010 @@ -47,7 +47,8 @@ else: cmdline = 'neato -Tplain' #print >> sys.stderr, '* running:', cmdline - p = subprocess.Popen(cmdline, shell=True, close_fds=True, + close_fds = sys.platform != 'win32' + p = subprocess.Popen(cmdline, shell=True, close_fds=close_fds, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (child_in, child_out) = (p.stdin, p.stdout) try: Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py Sun Jun 20 18:38:42 2010 @@ -647,7 +647,9 @@ """ # The python library is always needed on Windows. if sys.platform == "win32": - pythonlib = 'libpypy-c.exe' + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py Sun Jun 20 18:38:42 2010 @@ -159,14 +159,60 @@ s = s.replace(k, v) return s +def get_manifests(): + """Retrieves the manifest(s) embedded in the current executable""" + import ctypes.wintypes + EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA + EnumResourceNameCallback = ctypes.WINFUNCTYPE( + ctypes.wintypes.BOOL, + ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, + ctypes.wintypes.LONG, ctypes.wintypes.LONG) + FindResource = ctypes.windll.kernel32.FindResourceA + LoadResource = ctypes.windll.kernel32.LoadResource + FreeResource = ctypes.windll.kernel32.FreeResource + SizeofResource = ctypes.windll.kernel32.SizeofResource + LockResource = ctypes.windll.kernel32.LockResource + UnlockResource = lambda x: None # hehe + + manifests = [] + + def callback(hModule, lpType, lpName, lParam): + hResource = FindResource(hModule, lpName, lpType) + size = SizeofResource(hModule, hResource) + hData = LoadResource(hModule, hResource) + try: + ptr = LockResource(hData) + try: + manifests.append(ctypes.string_at(ptr, size)) + finally: + UnlockResource(hData) + finally: + FreeResource(hData) + return True + + hModule = None # main executable + RT_MANIFEST = 24 # from WinUser.h + EnumResourceNames(hModule, RT_MANIFEST, + EnumResourceNameCallback(callback), None) + return manifests + def get_build_version(): """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. """ + try: + manifests = get_manifests() + for manifest in manifests: + match = re.search('"Microsoft.VC([0-9]+).CRT"', manifest) + if match: + return int(match.group(1)) / 10.0 + except BaseException: + pass + # No manifest embedded, use default compiler version return 9.0 +def get_build_architecture(): + return 'Intel' + def normalize_and_reduce_paths(paths): """Return a list of normalized paths with duplicates removed. Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Sun Jun 20 18:38:42 2010 @@ -13,6 +13,9 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j + cand = j(sys.pypy_prefix, 'include') + if os.path.exists(cand): + return cand if plat_specific: return j(sys.pypy_prefix, "pypy", "_interfaces") return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') Modified: pypy/branch/fast-forward/py/_code/_assertionnew.py ============================================================================== --- pypy/branch/fast-forward/py/_code/_assertionnew.py (original) +++ pypy/branch/fast-forward/py/_code/_assertionnew.py Sun Jun 20 18:38:42 2010 @@ -92,6 +92,7 @@ ast.LtE : "<=", ast.Gt : ">", ast.GtE : ">=", + ast.Pow : "**", ast.Is : "is", ast.IsNot : "is not", ast.In : "in", Modified: pypy/branch/fast-forward/py/_code/_assertionold.py ============================================================================== --- pypy/branch/fast-forward/py/_code/_assertionold.py (original) +++ pypy/branch/fast-forward/py/_code/_assertionold.py Sun Jun 20 18:38:42 2010 @@ -138,28 +138,28 @@ __view__ = ast.Name def is_local(self, frame): - co = compile('%r in locals() is not globals()' % self.name, '?', 'eval') + source = '%r in locals() is not globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_global(self, frame): - co = compile('%r in globals()' % self.name, '?', 'eval') + source = '%r in globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_builtin(self, frame): - co = compile('%r not in locals() and %r not in globals()' % ( - self.name, self.name), '?', 'eval') + source = '%r not in locals() and %r not in globals()' % ( + self.name, self.name) try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: @@ -185,11 +185,11 @@ expr2.eval(frame) self.explanation = "%s %s %s" % ( expr.explanation, operation, expr2.explanation) - co = compile("__exprinfo_left %s __exprinfo_right" % operation, - '?', 'eval') + source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(co, __exprinfo_left=expr.result, - __exprinfo_right=expr2.result) + self.result = frame.eval(source, + __exprinfo_left=expr.result, + __exprinfo_right=expr2.result) except passthroughex: raise except: @@ -235,14 +235,14 @@ class UnaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): expr = Interpretable(self.expr) expr.eval(frame) self.explanation = astpattern.replace('__exprinfo_expr', expr.explanation) try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(astpattern, + __exprinfo_expr=expr.result) except passthroughex: raise except: @@ -263,8 +263,7 @@ class BinaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): left = Interpretable(self.left) left.eval(frame) right = Interpretable(self.right) @@ -273,8 +272,9 @@ .replace('__exprinfo_left', left .explanation) .replace('__exprinfo_right', right.explanation)) try: - self.result = frame.eval(co, __exprinfo_left=left.result, - __exprinfo_right=right.result) + self.result = frame.eval(astpattern, + __exprinfo_left=left.result, + __exprinfo_right=right.result) except passthroughex: raise except: @@ -287,9 +287,10 @@ __view__ = ast.CallFunc def is_bool(self, frame): - co = compile('isinstance(__exprinfo_value, bool)', '?', 'eval') + source = 'isinstance(__exprinfo_value, bool)' try: - return frame.is_true(frame.eval(co, __exprinfo_value=self.result)) + return frame.is_true(frame.eval(source, + __exprinfo_value=self.result)) except passthroughex: raise except: @@ -336,9 +337,8 @@ if source.endswith(','): source = source[:-1] source += ')' - co = compile(source, '?', 'eval') try: - self.result = frame.eval(co, **vars) + self.result = frame.eval(source, **vars) except passthroughex: raise except: @@ -353,21 +353,20 @@ def eval(self, frame): expr = Interpretable(self.expr) expr.eval(frame) - co = compile('__exprinfo_expr.%s' % self.attrname, '?', 'eval') + source = '__exprinfo_expr.%s' % self.attrname try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(source, __exprinfo_expr=expr.result) except passthroughex: raise except: raise Failure(self) self.explanation = '%s.%s' % (expr.explanation, self.attrname) # if the attribute comes from the instance, its value is interesting - co = compile('hasattr(__exprinfo_expr, "__dict__") and ' - '%r in __exprinfo_expr.__dict__' % self.attrname, - '?', 'eval') + source = ('hasattr(__exprinfo_expr, "__dict__") and ' + '%r in __exprinfo_expr.__dict__' % self.attrname) try: from_instance = frame.is_true( - frame.eval(co, __exprinfo_expr=expr.result)) + frame.eval(source, __exprinfo_expr=expr.result)) except passthroughex: raise except: Modified: pypy/branch/fast-forward/py/_process/cmdexec.py ============================================================================== --- pypy/branch/fast-forward/py/_process/cmdexec.py (original) +++ pypy/branch/fast-forward/py/_process/cmdexec.py Sun Jun 20 18:38:42 2010 @@ -18,8 +18,10 @@ universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.getdefaultencoding()) - err = py.builtin._totext(err, sys.getdefaultencoding()) + out = py.builtin._totext(out, sys.stdout.encoding or + sys.getdefaultencoding()) + err = py.builtin._totext(err, sys.stderr.encoding or + sys.getdefaultencoding()) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) Modified: pypy/branch/fast-forward/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/builtin.py (original) +++ pypy/branch/fast-forward/pypy/annotation/builtin.py Sun Jun 20 18:38:42 2010 @@ -8,7 +8,7 @@ from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString from pypy.annotation.model import SomePBC, SomeInstance, SomeDict, SomeList -from pypy.annotation.model import SomeWeakRef +from pypy.annotation.model import SomeWeakRef, SomeIterator from pypy.annotation.model import SomeOOObject from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation from pypy.annotation.model import add_knowntypedata @@ -85,6 +85,9 @@ builtin_xrange = builtin_range # xxx for now allow it +def builtin_enumerate(s_obj): + return SomeIterator(s_obj, "enumerate") + def builtin_bool(s_obj): return s_obj.is_true() @@ -272,12 +275,6 @@ def OSError_init(s_self, *args): pass -def UnicodeDecodeError_init(s_self, *args): - pass - -def UnicodeEncodeError_init(s_self, *args): - pass - def WindowsError_init(s_self, *args): pass @@ -346,7 +343,7 @@ assert s_type.is_constant() return SomePtr(s_type.const) -def llmemory_cast_adr_to_int(s): +def llmemory_cast_adr_to_int(s, s_mode=None): return SomeInteger() # xxx def llmemory_cast_int_to_adr(s): @@ -396,8 +393,6 @@ BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = ( OSError_init) -BUILTIN_ANALYZERS[getattr(UnicodeDecodeError.__init__, 'im_func', UnicodeDecodeError.__init__)] = UnicodeDecodeError_init -BUILTIN_ANALYZERS[getattr(UnicodeEncodeError.__init__, 'im_func', UnicodeEncodeError.__init__)] = UnicodeEncodeError_init try: WindowsError Modified: pypy/branch/fast-forward/pypy/annotation/classdef.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/classdef.py (original) +++ pypy/branch/fast-forward/pypy/annotation/classdef.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,7 @@ """ from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\ - SomeString, SomeUnicodeString + SomeString from pypy.annotation import description @@ -439,16 +439,6 @@ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, - UnicodeDecodeError: {'end': SomeInteger(), - 'start': SomeInteger(), - 'object': SomeString(), - 'encoding': SomeString(), - 'reason': SomeString()}, - UnicodeEncodeError: {'end': SomeInteger(), - 'start': SomeInteger(), - 'object': SomeUnicodeString(), - 'encoding': SomeString(), - 'reason': SomeString()} } try: Modified: pypy/branch/fast-forward/pypy/annotation/description.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/description.py (original) +++ pypy/branch/fast-forward/pypy/annotation/description.py Sun Jun 20 18:38:42 2010 @@ -539,9 +539,18 @@ try: args.fixedunpack(0) except ValueError: - raise Exception("default __init__ takes no argument" " (class %s)" % (self.name,)) + elif self.pyobj is Exception: + # check explicitly against "raise Exception, x" where x + # is a low-level exception pointer + try: + [s_arg] = args.fixedunpack(1) + except ValueError: + pass + else: + from pypy.annotation.model import SomePtr + assert not isinstance(s_arg, SomePtr) else: # call the constructor args = args.prepend(s_instance) Modified: pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py Sun Jun 20 18:38:42 2010 @@ -3321,16 +3321,27 @@ s = a.build_types(g, [int]) assert a.bookkeeper.getdesc(f).getuniquegraph() - def test_unicode_decode_error(self): + def test_cannot_raise_ll_exception(self): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + # def f(): - try: - raise UnicodeDecodeError("x", "x", 0, 1, "reason") - except UnicodeDecodeError, ude: - return ude.end + e = OverflowError() + lle = cast_instance_to_base_ptr(e) + raise Exception, lle + # ^^^ instead, must cast back from a base ptr to an instance + a = self.RPythonAnnotator() + py.test.raises(AssertionError, a.build_types, f, []) + def test_enumerate(self): + def f(): + for i, x in enumerate(['a', 'b', 'c', 'd']): + if i == 2: + return x + return '?' a = self.RPythonAnnotator() s = a.build_types(f, []) - assert isinstance(s, annmodel.SomeInteger) + assert isinstance(s, annmodel.SomeChar) + def g(n): return [0,1,2,n] Modified: pypy/branch/fast-forward/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/unaryop.py (original) +++ pypy/branch/fast-forward/pypy/annotation/unaryop.py Sun Jun 20 18:38:42 2010 @@ -577,6 +577,9 @@ return can_throw def next(itr): + if itr.variant == ("enumerate",): + s_item = itr.s_container.getanyitem() + return SomeTuple((SomeInteger(nonneg=True), s_item)) return itr.s_container.getanyitem(*itr.variant) next.can_only_throw = _can_only_throw method_next = next Modified: pypy/branch/fast-forward/pypy/doc/how-to-release.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/how-to-release.txt (original) +++ pypy/branch/fast-forward/pypy/doc/how-to-release.txt Sun Jun 20 18:38:42 2010 @@ -4,12 +4,13 @@ Overview --------- -As a meta rule setting up issues in the tracker for items here may help not forgetting things. -A set of todo files may also work. +As a meta rule setting up issues in the tracker for items here may help not +forgetting things. A set of todo files may also work. Check and prioritize all issues for the release, postpone some if necessary, -create new issues also as necessary. A meeting (or meetings) should be organized -to decide what things are priorities, should go in and work for the release. +create new issues also as necessary. A meeting (or meetings) should be +organized to decide what things are priorities, should go in and work for +the release. An important thing is to get the documentation into an up-to-date state! @@ -25,34 +26,21 @@ necessary * update pypy/doc/contributor.txt (and possibly LICENSE) * update README -* update pypy.org (under extradoc/pypy.org), rebuild and commit -* build following binaries (supported versions for now): - JIT: windows, linux, os/x - no JIT: windows, linux, os/x - sandbox: linux, os/x - stackless: windows, linux, os/x +* go to pypy/tool/release and run: + force-builds.py /release/ +* wait for builds to complete, make sure there are no failures +* run pypy/tool/release/make_release.py, this will build necessary binaries + and upload them to pypy.org + + Following binaries should be built, however, we need more buildbots: + JIT: windows, linux, os/x + no JIT: windows, linux, os/x + sandbox: linux, os/x + stackless: windows, linux, os/x -XXX stuff below is out-of-date or at least needs some review * write release announcement pypy/doc/release-x.y(.z).txt the release announcement should contain a direct link to the download page -* update pypy/doc/getting-started.txt links at the top - and release number references, make sure it is generally up-to-date -* use, after the necessary updates, pypy/tool/makerelease.py to - make the tarballs on codespeak; this generates html doc for the - tarballs too. Use:: - - makerelease -tag .z pypy-x.y.z - - to tag and produce final tarballs. Without the '-tag' this can - be used to make pre-release testing tarballs. -* nowadays we have an extensive set of nightly builds and test - runs. Is probably good to do some minimal testing of the tarballs, - especially to check that things work even outside a working copy or - if some stuff is missing. We have some support for running part of - our nightly tests on tarballs (see - http://codespeak.net/svn/user/pedronis/tarball-testing). -* write a news item for the release in pypy/doc/news.txt -* update http://codespeak.net/svn/pypy/dist and codespeak's - precomputed html files -* send announcements to pypy-dev, pypy-funding, python-list, +* update pypy.org (under extradoc/pypy.org), rebuild and commit +* post announcement on morepypy.blogspot.com +* send announcements to pypy-dev, python-list, python-announce, python-dev ... Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_function.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_function.py Sun Jun 20 18:38:42 2010 @@ -158,13 +158,6 @@ assert res[0] == 42 assert res[1] == {'something': 23} - def test_kwargs_sets_positional_mixed(self): - def func(arg1, **kw): - return arg1, kw - res = func(arg1=42, something=23) - assert res[0] == 42 - assert res[1] == {'something': 23} - def test_kwargs_sets_positional_twice(self): def func(arg1, **kw): return arg1, kw Modified: pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llgraph/llimpl.py Sun Jun 20 18:38:42 2010 @@ -4,12 +4,12 @@ when executing on top of the llinterpreter. """ -import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel -from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, +from pypy.jit.metainterp.history import (ConstInt, ConstPtr, BoxInt, BoxPtr, BoxObj, BoxFloat, REF, INT, FLOAT) +from pypy.jit.codewriter import heaptracker from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport @@ -73,12 +73,12 @@ 'int_eq' : (('int', 'int'), 'bool'), 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), + 'int_is_zero' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), - 'bool_not' : (('bool',), 'bool'), 'uint_add' : (('int', 'int'), 'int'), 'uint_sub' : (('int', 'int'), 'int'), 'uint_mul' : (('int', 'int'), 'int'), @@ -103,7 +103,6 @@ 'float_ge' : (('float', 'float'), 'bool'), 'float_neg' : (('float',), 'float'), 'float_abs' : (('float',), 'float'), - 'float_is_true' : (('float',), 'bool'), 'cast_float_to_int':(('float',), 'int'), 'cast_int_to_float':(('int',), 'float'), 'same_as' : (('int',), 'int'), # could also be ptr=>ptr @@ -127,7 +126,6 @@ 'arraylen_gc' : (('ref',), 'int'), 'call' : (('ref', 'varargs'), 'intorptr'), 'call_assembler' : (('ref', 'varargs'), 'intorptr'), - 'call_pure' : (('ref', 'varargs'), 'intorptr'), 'cond_call_gc_wb' : (('ptr', 'ptr'), None), 'oosend' : (('varargs',), 'intorptr'), 'oosend_pure' : (('varargs',), 'intorptr'), @@ -155,16 +153,6 @@ 'force_token' : ((), 'int'), 'call_may_force' : (('int', 'varargs'), 'intorptr'), 'guard_not_forced': ((), None), - 'virtual_ref' : (('ref', 'int'), 'ref'), - 'virtual_ref_finish': (('ref', 'ref'), None), - #'getitem' : (('void', 'ref', 'int'), 'int'), - #'setitem' : (('void', 'ref', 'int', 'int'), None), - #'newlist' : (('void', 'varargs'), 'ref'), - #'append' : (('void', 'ref', 'int'), None), - #'insert' : (('void', 'ref', 'int', 'int'), None), - #'pop' : (('void', 'ref',), 'int'), - #'len' : (('void', 'ref',), 'int'), - #'listnonzero' : (('void', 'ref',), 'int'), } # ____________________________________________________________ @@ -231,19 +219,19 @@ else: return repr(x) -def repr_list(lst, types, memocast): +def repr_list(lst, types): res_l = [] if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, memocast)) + res_l.append('(%s)' % repr1(elem, tp)) else: - res_l.append(repr1(elem, tp, memocast)) + res_l.append(repr1(elem, tp)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, memocast): +def repr1(x, tp): if tp == "intorptr": TYPE = lltype.typeOf(x) if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': @@ -259,7 +247,7 @@ return '(* None)' if isinstance(x, int): # XXX normalize? - ptr = str(cast_int_to_adr(memocast, x)) + ptr = str(llmemory.cast_int_to_adr(x)) elif isinstance(ootype.typeOf(x), ootype.OOType): return repr(x) else: @@ -400,10 +388,9 @@ class Frame(object): OPHANDLERS = [None] * (rop._LAST+1) - def __init__(self, memocast, cpu): + def __init__(self, cpu): self.verbose = False self.cpu = cpu - self.memocast = memocast self.opindex = 1 self._forced = False self._may_force = -1 @@ -522,15 +509,14 @@ elif res is NotImplemented: resdata = '*fail*' else: - resdata = '-> ' + repr1(res, restype, self.memocast) + resdata = '-> ' + repr1(res, restype) # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), + log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes), resdata)) return res def as_int(self, x): - return cast_to_int(x, self.memocast) + return cast_to_int(x) def as_ptr(self, x): return cast_to_ptr(x) @@ -554,34 +540,36 @@ try: op = getattr(cls, 'op_' + opname.lower()) # op_guard_true etc. except AttributeError: - name = 'do_' + opname.lower() try: - impl = globals()[name] # do_arraylen_gc etc. + impl = globals()['do_' + opname.lower()] # do_arraylen_gc etc. def op(self, descr, *args): - return impl(descr, *args) - # + if descr is None: + return impl(*args) + else: + return impl(descr, *args) except KeyError: - from pypy.jit.backend.llgraph import llimpl - impl = getattr(executor, name) # do_int_add etc. - def _op_default_implementation(self, descr, *args): - # for all operations implemented in execute.py - boxedargs = [] - for x in args: - if type(x) is int: - boxedargs.append(BoxInt(x)) - elif type(x) is float: - boxedargs.append(BoxFloat(x)) - elif isinstance(ootype.typeOf(x), ootype.OOType): - boxedargs.append(BoxObj(ootype.cast_to_object(x))) - else: - boxedargs.append(BoxPtr(x)) - # xxx this passes the 'llimpl' module as the CPU argument - resbox = impl(llimpl, *boxedargs) - return getattr(resbox, 'value', None) - op = _op_default_implementation - # + op = cls._make_impl_from_blackhole_interp(opname) cls.OPHANDLERS[opnum] = op + @classmethod + def _make_impl_from_blackhole_interp(cls, opname): + from pypy.jit.metainterp.blackhole import BlackholeInterpreter + name = 'bhimpl_' + opname.lower() + func = BlackholeInterpreter.__dict__[name] + for argtype in func.argtypes: + assert argtype in ('i', 'r', 'f') + # + def _op_default_implementation(self, descr, *args): + # for all operations implemented in the blackhole interpreter + return func(*args) + # + return _op_default_implementation + + def op_debug_merge_point(self, _, value): + from pypy.jit.metainterp.warmspot import get_stats + loc = ConstPtr(value)._get_str() + get_stats().add_merge_point_location(loc) + def op_guard_true(self, _, value): if not value: raise GuardFailed @@ -596,7 +584,7 @@ def op_guard_class(self, _, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_class), + llmemory.cast_int_to_adr(expected_class), rclass.CLASSTYPE) if value.typeptr != expected_class: raise GuardFailed @@ -630,7 +618,7 @@ def _cast_exception(self, exception): return llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, exception), + llmemory.cast_int_to_adr(exception), rclass.CLASSTYPE) def _issubclass(self, cls1, cls2): @@ -696,7 +684,7 @@ if arraydescr.typeinfo == REF: return do_getarrayitem_gc_ptr(array, index) elif arraydescr.typeinfo == INT: - return do_getarrayitem_gc_int(array, index, self.memocast) + return do_getarrayitem_gc_int(array, index) elif arraydescr.typeinfo == FLOAT: return do_getarrayitem_gc_float(array, index) else: @@ -708,7 +696,7 @@ if fielddescr.typeinfo == REF: return do_getfield_gc_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_gc_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: return do_getfield_gc_float(struct, fielddescr.ofs) else: @@ -718,11 +706,11 @@ def op_getfield_raw(self, fielddescr, struct): if fielddescr.typeinfo == REF: - return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_ptr(struct, fielddescr.ofs) elif fielddescr.typeinfo == INT: - return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_int(struct, fielddescr.ofs) elif fielddescr.typeinfo == FLOAT: - return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast) + return do_getfield_raw_float(struct, fielddescr.ofs) else: raise NotImplementedError @@ -733,17 +721,17 @@ def op_new_with_vtable(self, descr, vtable): assert descr is None - size = get_class_size(self.memocast, vtable) - result = do_new(size) + descr = heaptracker.vtable2descr(self.cpu, vtable) + result = do_new(descr.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) - value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) + value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr.typeinfo == REF: do_setarrayitem_gc_ptr(array, index, newvalue) elif arraydescr.typeinfo == INT: - do_setarrayitem_gc_int(array, index, newvalue, self.memocast) + do_setarrayitem_gc_int(array, index, newvalue) elif arraydescr.typeinfo == FLOAT: do_setarrayitem_gc_float(array, index, newvalue) else: @@ -753,8 +741,7 @@ if fielddescr.typeinfo == REF: do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_gc_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: do_setfield_gc_float(struct, fielddescr.ofs, newvalue) else: @@ -762,32 +749,41 @@ def op_setfield_raw(self, fielddescr, struct, newvalue): if fielddescr.typeinfo == REF: - do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == INT: - do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_int(struct, fielddescr.ofs, newvalue) elif fielddescr.typeinfo == FLOAT: - do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memocast) + do_setfield_raw_float(struct, fielddescr.ofs, newvalue) else: raise NotImplementedError def op_call(self, calldescr, func, *args): - _call_args[:] = args - if calldescr.typeinfo == 'v': - err_result = None - elif calldescr.typeinfo == REF: - err_result = lltype.nullptr(llmemory.GCREF.TO) - elif calldescr.typeinfo == INT: - err_result = 0 - elif calldescr.typeinfo == FLOAT: - err_result = 0.0 - else: - raise NotImplementedError - return _do_call_common(func, self.memocast, err_result) - - op_call_pure = op_call + global _last_exception + assert _last_exception is None, "exception left behind" + assert _call_args_i == _call_args_r == _call_args_f == [] + args_in_order = [] + for x in args: + T = lltype.typeOf(x) + if T is lltype.Signed: + args_in_order.append('i') + _call_args_i.append(x) + elif T == llmemory.GCREF: + args_in_order.append('r') + _call_args_r.append(x) + elif T is lltype.Float: + args_in_order.append('f') + _call_args_f.append(x) + else: + raise TypeError(x) + try: + return _do_call_common(func, args_in_order) + except LLException, lle: + _last_exception = lle + d = {'v': None, + REF: lltype.nullptr(llmemory.GCREF.TO), + INT: 0, + FLOAT: 0.0} + return d[calldescr.typeinfo] def op_cond_call_gc_wb(self, descr, a, b): py.test.skip("cond_call_gc_wb not supported") @@ -801,7 +797,7 @@ return do_new_array(arraydescr.ofs, count) def op_cast_ptr_to_int(self, descr, ptr): - return cast_to_int(ptr, self.memocast) + return cast_to_int(ptr) def op_uint_xor(self, descr, arg1, arg2): return arg1 ^ arg2 @@ -859,12 +855,6 @@ if forced: raise GuardFailed - def op_virtual_ref(self, _, virtual, index): - return virtual - - def op_virtual_ref_finish(self, _, vref, virtual): - pass - class OOFrame(Frame): @@ -925,19 +915,17 @@ def op_call(self, calldescr, func, *args): sm = ootype.cast_from_object(calldescr.FUNC, func) - newargs = cast_call_args(calldescr.FUNC.ARGS, args, self.memocast) + newargs = cast_call_args(calldescr.FUNC.ARGS, args) res = call_maybe_on_top_of_llinterp(sm, newargs) if isinstance(calldescr.FUNC.RESULT, ootype.OOType): return ootype.cast_to_object(res) return res - op_call_pure = op_call - def op_oosend(self, descr, obj, *args): METH = descr.METH obj = ootype.cast_from_object(descr.SELFTYPE, obj) meth = getattr(obj, descr.methname) - newargs = cast_call_args(METH.ARGS, args, self.memocast) + newargs = cast_call_args(METH.ARGS, args) res = call_maybe_on_top_of_llinterp(meth, newargs) if isinstance(METH.RESULT, ootype.OOType): return ootype.cast_to_object(res) @@ -973,27 +961,27 @@ # ____________________________________________________________ -def cast_to_int(x, memocast): +def cast_to_int(x): TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): - return cast_adr_to_int(memocast, llmemory.cast_ptr_to_adr(x)) + return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return cast_adr_to_int(memocast, x) + return heaptracker.adr2int(x) return lltype.cast_primitive(lltype.Signed, x) -def cast_from_int(TYPE, x, memocast): +def cast_from_int(TYPE, x): if isinstance(TYPE, lltype.Ptr): - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) elif TYPE == llmemory.Address: - if isinstance(x, (int, long)): - x = cast_int_to_adr(memocast, x) + if isinstance(x, (int, long, llmemory.AddressAsInt)): + x = llmemory.cast_int_to_adr(x) assert lltype.typeOf(x) == llmemory.Address return x else: if lltype.typeOf(x) == llmemory.Address: - x = cast_adr_to_int(memocast, x) + x = heaptracker.adr2int(x) return lltype.cast_primitive(TYPE, x) def cast_to_ptr(x): @@ -1013,11 +1001,11 @@ return x -def new_frame(memocast, is_oo, cpu): +def new_frame(is_oo, cpu): if is_oo: - frame = OOFrame(memocast, cpu) + frame = OOFrame(cpu) else: - frame = Frame(memocast, cpu) + frame = Frame(cpu) return _to_opaque(frame) _future_values = [] @@ -1067,69 +1055,68 @@ def frame_int_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Signed + return x def frame_float_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) is lltype.Float + return x def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - result = frame.fail_args[num] - frame.fail_args[num] = None - return result + assert num >= 0 + x = frame.fail_args[num] + assert lltype.typeOf(x) == llmemory.GCREF + return x -_last_exception = None +def frame_get_value_count(frame): + frame = _from_opaque(frame) + return len(frame.fail_args) -def get_exception(): - if _last_exception: - return llmemory.cast_ptr_to_adr(_last_exception.args[0]) - else: - return llmemory.NULL +def frame_clear_latest_values(frame, count): + frame = _from_opaque(frame) + assert count == len(frame.fail_args) + del frame.fail_args -def get_exc_value(): - if _last_exception: - return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) - else: - return lltype.nullptr(llmemory.GCREF.TO) +_last_exception = None -def clear_exception(): +def grab_exc_value(): global _last_exception - _last_exception = None + if _last_exception is not None: + result = _last_exception.args[1] + _last_exception = None + return lltype.cast_opaque_ptr(llmemory.GCREF, result) + else: + return lltype.nullptr(llmemory.GCREF.TO) -_pseudo_exceptions = {} +##_pseudo_exceptions = {} -def _get_error(Class): - if _llinterp.typer is not None: - llframe = _llinterp.frame_class(None, None, _llinterp) - try: - llframe.make_llexception(Class()) - except LLException, e: - return e - else: - assert 0, "should have raised" - else: - # for tests, a random emulated ll_inst will do - if Class not in _pseudo_exceptions: - ll_inst = lltype.malloc(rclass.OBJECT, zero=True) - ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, - immortal=True) - _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) - return _pseudo_exceptions[Class] - -def get_overflow_error(): - return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0]) - -def get_overflow_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(OverflowError).args[1]) - -def get_zero_division_error(): - return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0]) - -def get_zero_division_error_value(): - return lltype.cast_opaque_ptr(llmemory.GCREF, - _get_error(ZeroDivisionError).args[1]) +##def _get_error(Class): +## if _llinterp.typer is not None: +## llframe = _llinterp.frame_class(None, None, _llinterp) +## try: +## llframe.make_llexception(Class()) +## except LLException, e: +## return e +## else: +## assert 0, "should have raised" +## else: +## # for tests, a random emulated ll_inst will do +## if Class not in _pseudo_exceptions: +## ll_inst = lltype.malloc(rclass.OBJECT, zero=True) +## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, +## immortal=True) +## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) +## return _pseudo_exceptions[Class] + +##def get_overflow_error_value(): +## return lltype.cast_opaque_ptr(llmemory.GCREF, +## _get_error(OverflowError).args[1]) def force(opaque_frame): frame = _from_opaque(opaque_frame) @@ -1151,40 +1138,30 @@ def get_frame_forced_token(opaque_frame): return llmemory.cast_ptr_to_adr(opaque_frame) -class MemoCast(object): - def __init__(self): - self.addresses = [llmemory.NULL] - self.rev_cache = {} - self.vtable_to_size = {} - -def new_memo_cast(): - memocast = MemoCast() - return _to_opaque(memocast) - -def cast_adr_to_int(memocast, adr): - # xxx slow - assert lltype.typeOf(adr) == llmemory.Address - memocast = _from_opaque(memocast) - addresses = memocast.addresses - for i in xrange(len(addresses)-1, -1, -1): - if addresses[i] == adr: - return i - i = len(addresses) - addresses.append(adr) - return i - -def cast_int_to_adr(memocast, int): - memocast = _from_opaque(memocast) - assert 0 <= int < len(memocast.addresses) - return memocast.addresses[int] - -def get_class_size(memocast, vtable): - memocast = _from_opaque(memocast) - return memocast.vtable_to_size[vtable] - -def set_class_size(memocast, vtable, size): - memocast = _from_opaque(memocast) - memocast.vtable_to_size[vtable] = size +##def cast_adr_to_int(memocast, adr): +## # xxx slow +## assert lltype.typeOf(adr) == llmemory.Address +## memocast = _from_opaque(memocast) +## addresses = memocast.addresses +## for i in xrange(len(addresses)-1, -1, -1): +## if addresses[i] == adr: +## return i +## i = len(addresses) +## addresses.append(adr) +## return i + +##def cast_int_to_adr(memocast, int): +## memocast = _from_opaque(memocast) +## assert 0 <= int < len(memocast.addresses) +## return memocast.addresses[int] + +##def get_class_size(memocast, vtable): +## memocast = _from_opaque(memocast) +## return memocast.vtable_to_size[vtable] + +##def set_class_size(memocast, vtable, size): +## memocast = _from_opaque(memocast) +## memocast.vtable_to_size[vtable] = size class GuardFailed(Exception): pass @@ -1192,29 +1169,32 @@ # ____________________________________________________________ +def do_same_as(x): + return x + def do_arraylen_gc(arraydescr, array): array = array._obj.container return array.getlength() -def do_strlen(_, string): +def do_strlen(string): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return len(str.chars) -def do_strgetitem(_, string, index): +def do_strgetitem(string, index): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) -def do_unicodelen(_, string): +def do_unicodelen(string): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return len(uni.chars) -def do_unicodegetitem(_, string, index): +def do_unicodegetitem(string, index): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) return ord(uni.chars[index]) -def do_getarrayitem_gc_int(array, index, memocast): +def do_getarrayitem_gc_int(array, index): array = array._obj.container - return cast_to_int(array.getitem(index), memocast) + return cast_to_int(array.getitem(index)) def do_getarrayitem_gc_float(array, index): array = array._obj.container @@ -1229,8 +1209,8 @@ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_gc_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_gc(struct, fieldnum), memocast) +def do_getfield_gc_int(struct, fieldnum): + return cast_to_int(_getfield_gc(struct, fieldnum)) def do_getfield_gc_float(struct, fieldnum): return cast_to_float(_getfield_gc(struct, fieldnum)) @@ -1238,19 +1218,19 @@ def do_getfield_gc_ptr(struct, fieldnum): return cast_to_ptr(_getfield_gc(struct, fieldnum)) -def _getfield_raw(struct, fieldnum, memocast): +def _getfield_raw(struct, fieldnum): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) return getattr(ptr, fieldname) -def do_getfield_raw_int(struct, fieldnum, memocast): - return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast) +def do_getfield_raw_int(struct, fieldnum): + return cast_to_int(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_float(struct, fieldnum, memocast): - return cast_to_float(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_float(struct, fieldnum): + return cast_to_float(_getfield_raw(struct, fieldnum)) -def do_getfield_raw_ptr(struct, fieldnum, memocast): - return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast)) +def do_getfield_raw_ptr(struct, fieldnum): + return cast_to_ptr(_getfield_raw(struct, fieldnum)) def do_new(size): TYPE = symbolic.Size2Type[size] @@ -1262,10 +1242,10 @@ x = lltype.malloc(TYPE, count, zero=True) return cast_to_ptr(x) -def do_setarrayitem_gc_int(array, index, newvalue, memocast): +def do_setarrayitem_gc_int(array, index, newvalue): array = array._obj.container ITEMTYPE = lltype.typeOf(array).OF - newvalue = cast_from_int(ITEMTYPE, newvalue, memocast) + newvalue = cast_from_int(ITEMTYPE, newvalue) array.setitem(index, newvalue) def do_setarrayitem_gc_float(array, index, newvalue): @@ -1280,11 +1260,11 @@ newvalue = cast_from_ptr(ITEMTYPE, newvalue) array.setitem(index, newvalue) -def do_setfield_gc_int(struct, fieldnum, newvalue, memocast): +def do_setfield_gc_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) def do_setfield_gc_float(struct, fieldnum, newvalue): @@ -1301,108 +1281,129 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_int(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_int(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + newvalue = cast_from_int(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_float(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_float(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_float(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast): +def do_setfield_raw_ptr(struct, fieldnum, newvalue): STRUCT, fieldname = symbolic.TokenToField[fieldnum] - ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast) + ptr = cast_from_int(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_newstr(_, length): +def do_newstr(length): x = rstr.mallocstr(length) return cast_to_ptr(x) -def do_newunicode(_, length): +def do_newunicode(length): return cast_to_ptr(rstr.mallocunicode(length)) -def do_strsetitem(_, string, index, newvalue): +def do_strsetitem(string, index, newvalue): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) -def do_unicodesetitem(_, string, index, newvalue): +def do_unicodesetitem(string, index, newvalue): uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) uni.chars[index] = unichr(newvalue) # ---------- call ---------- -_call_args = [] +_call_args_i = [] +_call_args_r = [] +_call_args_f = [] def do_call_pushint(x): - _call_args.append(x) - -def do_call_pushfloat(x): - _call_args.append(x) + _call_args_i.append(x) def do_call_pushptr(x): - _call_args.append(x) + _call_args_r.append(x) -def _do_call_common(f, memocast, err_result=None): - global _last_exception - assert _last_exception is None, "exception left behind" - ptr = cast_int_to_adr(memocast, f).ptr +def do_call_pushfloat(x): + _call_args_f.append(x) + +def _do_call_common(f, args_in_order=None): + ptr = llmemory.cast_int_to_adr(f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS - args = cast_call_args(ARGS, _call_args, memocast) - del _call_args[:] + args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f, + args_in_order) + del _call_args_i[:] + del _call_args_r[:] + del _call_args_f[:] assert len(ARGS) == len(args) - try: - if hasattr(ptr._obj, 'graph'): - llinterp = _llinterp # it's a global set here by CPU.__init__() - result = llinterp.eval_graph(ptr._obj.graph, args) - else: - result = ptr._obj._callable(*args) - except LLException, e: - _last_exception = e - result = err_result + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() + result = llinterp.eval_graph(ptr._obj.graph, args) + # ^^^ may raise, in which case we get an LLException + else: + result = ptr._obj._callable(*args) return result -def do_call_void(f, memocast): - _do_call_common(f, memocast) +def do_call_void(f): + _do_call_common(f) -def do_call_int(f, memocast): - x = _do_call_common(f, memocast, 0) - return cast_to_int(x, memocast) +def do_call_int(f): + x = _do_call_common(f) + return cast_to_int(x) -def do_call_float(f, memocast): - x = _do_call_common(f, memocast, 0) +def do_call_float(f): + x = _do_call_common(f) return cast_to_float(x) -def do_call_ptr(f, memocast): - x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO)) +def do_call_ptr(f): + x = _do_call_common(f) return cast_to_ptr(x) -def cast_call_args(ARGS, args, memocast): - argsiter = iter(args) +def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None): + argsiter_i = iter(args_i) + argsiter_r = iter(args_r) + argsiter_f = iter(args_f) + if args_in_order is not None: + orderiter = iter(args_in_order) args = [] for TYPE in ARGS: if TYPE is lltype.Void: x = None else: - x = argsiter.next() if isinstance(TYPE, ootype.OOType): + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = ootype.cast_from_object(TYPE, x) elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': + if args_in_order is not None: + n = orderiter.next() + assert n == 'r' + x = argsiter_r.next() x = cast_from_ptr(TYPE, x) elif TYPE is lltype.Float: + if args_in_order is not None: + n = orderiter.next() + assert n == 'f' + x = argsiter_f.next() x = cast_from_float(TYPE, x) else: - x = cast_from_int(TYPE, x, memocast) + if args_in_order is not None: + n = orderiter.next() + assert n == 'i' + x = argsiter_i.next() + x = cast_from_int(TYPE, x) args.append(x) - assert list(argsiter) == [] + assert list(argsiter_i) == [] + assert list(argsiter_r) == [] + assert list(argsiter_f) == [] return args @@ -1421,7 +1422,7 @@ result = llinterp.eval_graph(mymethod.graph, myargs) else: result = meth(*args) - except LLException, e: + except XXX-LLException, e: _last_exception = e result = get_err_result_for_type(mymethod._TYPE.RESULT) return result @@ -1474,16 +1475,13 @@ COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame")) -MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[OOFrame] = OOFRAME.TO -_TO_OPAQUE[MemoCast] = MEMOCAST.TO s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) s_Frame = annmodel.SomePtr(FRAME) -s_MemoCast = annmodel.SomePtr(MEMOCAST) setannotation(compile_start, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) @@ -1512,23 +1510,14 @@ setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) setannotation(frame_float_getvalue, annmodel.SomeFloat()) +setannotation(frame_get_value_count, annmodel.SomeInteger()) +setannotation(frame_clear_latest_values, annmodel.s_None) -setannotation(get_exception, annmodel.SomeAddress()) -setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(clear_exception, annmodel.s_None) -setannotation(get_overflow_error, annmodel.SomeAddress()) -setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF)) -setannotation(get_zero_division_error, annmodel.SomeAddress()) -setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF)) setannotation(force, annmodel.SomeInteger()) setannotation(get_forced_token_frame, s_Frame) setannotation(get_frame_forced_token, annmodel.SomeAddress()) -setannotation(new_memo_cast, s_MemoCast) -setannotation(cast_adr_to_int, annmodel.SomeInteger()) -setannotation(cast_int_to_adr, annmodel.SomeAddress()) -setannotation(set_class_size, annmodel.s_None) - setannotation(do_arraylen_gc, annmodel.SomeInteger()) setannotation(do_strlen, annmodel.SomeInteger()) setannotation(do_strgetitem, annmodel.SomeInteger()) Modified: pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llgraph/runner.py Sun Jun 20 18:38:42 2010 @@ -15,6 +15,7 @@ from pypy.jit.backend import model from pypy.jit.backend.llgraph import llimpl, symbolic from pypy.jit.metainterp.typesystem import llhelper, oohelper +from pypy.jit.codewriter import heaptracker from pypy.rlib import rgc class MiniStats: @@ -23,11 +24,19 @@ class Descr(history.AbstractDescr): - def __init__(self, ofs, typeinfo, extrainfo=None, name=None): + def __init__(self, ofs, typeinfo, extrainfo=None, name=None, + arg_types=None): self.ofs = ofs self.typeinfo = typeinfo self.extrainfo = extrainfo self.name = name + self.arg_types = arg_types + + def get_arg_types(self): + return self.arg_types + + def get_return_type(self): + return self.typeinfo def get_extra_info(self): return self.extrainfo @@ -51,6 +60,9 @@ def is_array_of_floats(self): return self.typeinfo == FLOAT + def as_vtable_size_descr(self): + return self + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -86,7 +98,6 @@ self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.stats.exec_conditional_jumps = 0 - self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._llinterp = LLInterpreter(self.rtyper) self._future_values = [] @@ -96,22 +107,16 @@ assert self.translate_support_code return False - def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None): - key = (ofs, typeinfo, extrainfo, name) + def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None, + arg_types=None): + key = (ofs, typeinfo, extrainfo, name, arg_types) try: return self._descrs[key] except KeyError: - descr = Descr(ofs, typeinfo, extrainfo, name) + descr = Descr(ofs, typeinfo, extrainfo, name, arg_types) self._descrs[key] = descr return descr - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - for vtable, size in class_sizes.items(): - if not self.is_oo: - size = size.ofs - llimpl.set_class_size(self.memo_cast, vtable, size) - def compile_bridge(self, faildescr, inputargs, operations): c = llimpl.compile_start() self._compile_loop_or_bridge(c, inputargs, operations) @@ -161,8 +166,6 @@ llimpl.compile_add_int_const(c, x.value) elif isinstance(x, self.ts.ConstRef): llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) elif isinstance(x, history.ConstFloat): llimpl.compile_add_float_const(c, x.value) else: @@ -213,7 +216,7 @@ def _execute_token(self, loop_token): compiled_version = loop_token._llgraph_compiled_version - frame = llimpl.new_frame(self.memo_cast, self.is_oo, self) + frame = llimpl.new_frame(self.is_oo, self) # setup the frame llimpl.frame_clear(frame, compiled_version) # run the loop @@ -247,60 +250,22 @@ def get_latest_value_float(self, index): return llimpl.frame_float_getvalue(self.latest_frame, index) + def get_latest_value_count(self): + return llimpl.frame_get_value_count(self.latest_frame) + def get_latest_force_token(self): token = llimpl.get_frame_forced_token(self.latest_frame) - return self.cast_adr_to_int(token) + return heaptracker.adr2int(token) - def make_boxes_from_latest_values(self, faildescr): - inputargs_and_holes = [] - for i in range(len(faildescr._fail_args_types)): - boxtype = faildescr._fail_args_types[i] - if boxtype == history.INT: - box = history.BoxInt(self.get_latest_value_int(i)) - elif boxtype == history.REF: - box = self.ts.BoxRef(self.get_latest_value_ref(i)) - elif boxtype == history.FLOAT: - box = history.BoxFloat(self.get_latest_value_float(i)) - elif boxtype == history.HOLE: - box = None - else: - assert False, "bad box type: num=%d" % ord(boxtype) - inputargs_and_holes.append(box) - return inputargs_and_holes + def clear_latest_values(self, count): + llimpl.frame_clear_latest_values(self.latest_frame, count) # ---------- - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) - - def get_exc_value(self): - return llimpl.get_exc_value() - - def clear_exception(self): - llimpl.clear_exception() - - def get_overflow_error(self): - return (self.cast_adr_to_int(llimpl.get_overflow_error()), - llimpl.get_overflow_error_value()) - - def get_zero_division_error(self): - return (self.cast_adr_to_int(llimpl.get_zero_division_error()), - llimpl.get_zero_division_error_value()) - def sizeof(self, S): assert not isinstance(S, lltype.Ptr) return self.getdescr(symbolic.get_size(S)) - def cast_adr_to_int(self, adr): - return llimpl.cast_adr_to_int(self.memo_cast, adr) - - def cast_int_to_adr(self, int): - return llimpl.cast_int_to_adr(self.memo_cast, int) - - def cast_gcref_to_int(self, gcref): - return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref)) - - class LLtypeCPU(BaseCPU): is_oo = False @@ -316,14 +281,17 @@ return self.getdescr(ofs, token[0], name=fieldname) def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): + arg_types = [] + for ARG in ARGS: + token = history.getkind(ARG) + if token != 'void': + arg_types.append(token[0]) token = history.getkind(RESULT) - return self.getdescr(0, token[0], extrainfo=extrainfo) - - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) + return self.getdescr(0, token[0], extrainfo=extrainfo, + arg_types=''.join(arg_types)) - def get_exc_value(self): - return llimpl.get_exc_value() + def grab_exc_value(self): + return llimpl.grab_exc_value() def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) @@ -334,202 +302,151 @@ # ---------- the backend-dependent operations ---------- - def do_arraylen_gc(self, arraybox, arraydescr): - array = arraybox.getref_base() - return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - - def do_strlen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_strlen(0, string)) - - def do_strgetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_strgetitem(0, string, index)) - - def do_unicodelen(self, stringbox): - string = stringbox.getref_base() - return history.BoxInt(llimpl.do_unicodelen(0, string)) - - def do_unicodegetitem(self, stringbox, indexbox): - string = stringbox.getref_base() - index = indexbox.getint() - return history.BoxInt(llimpl.do_unicodegetitem(0, string, index)) + def bh_strlen(self, string): + return llimpl.do_strlen(string) + + def bh_strgetitem(self, string, index): + return llimpl.do_strgetitem(string, index) + + def bh_unicodelen(self, string): + return llimpl.do_unicodelen(string) + + def bh_unicodegetitem(self, string, index): + return llimpl.do_unicodegetitem(string, index) - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) - elif arraydescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, - self.memo_cast)) - elif arraydescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array, - index)) - else: - raise NotImplementedError + return llimpl.do_getarrayitem_gc_int(array, index) + def bh_getarrayitem_gc_r(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_ptr(array, index) + def bh_getarrayitem_gc_f(self, arraydescr, array, index): + assert isinstance(arraydescr, Descr) + return llimpl.do_getarrayitem_gc_float(array, index) - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_gc_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, - fielddescr.ofs)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_gc_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_gc_float(struct, - fielddescr.ofs)) - else: - raise NotImplementedError + return llimpl.do_getfield_gc_int(struct, fielddescr.ofs) + def bh_getfield_gc_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_ptr(struct, fielddescr.ofs) + def bh_getfield_gc_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_gc_float(struct, fielddescr.ofs) - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == INT: - return history.BoxInt(llimpl.do_getfield_raw_int(struct, - fielddescr.ofs, - self.memo_cast)) - elif fielddescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_getfield_raw_float(struct, - fielddescr.ofs, - self.memo_cast)) - else: - raise NotImplementedError + return llimpl.do_getfield_raw_int(struct, fielddescr.ofs) + def bh_getfield_raw_r(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_ptr(struct, fielddescr.ofs) + def bh_getfield_raw_f(self, struct, fielddescr): + assert isinstance(fielddescr, Descr) + return llimpl.do_getfield_raw_float(struct, fielddescr.ofs) - def do_new(self, size): - assert isinstance(size, Descr) - return history.BoxPtr(llimpl.do_new(size.ofs)) - - def do_new_with_vtable(self, vtablebox): - vtable = vtablebox.getint() - size = self.class_sizes[vtable] - result = llimpl.do_new(size.ofs) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, - vtable, self.memo_cast) - return history.BoxPtr(result) - - def do_new_array(self, countbox, size): - assert isinstance(size, Descr) - count = countbox.getint() - return history.BoxPtr(llimpl.do_new_array(size.ofs, count)) + def bh_new(self, sizedescr): + assert isinstance(sizedescr, Descr) + return llimpl.do_new(sizedescr.ofs) + + def bh_new_with_vtable(self, sizedescr, vtable): + assert isinstance(sizedescr, Descr) + result = llimpl.do_new(sizedescr.ofs) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, vtable) + return result + + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_new_array(self, arraydescr, length): assert isinstance(arraydescr, Descr) - array = arraybox.getref_base() - index = indexbox.getint() - if arraydescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) - elif arraydescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setarrayitem_gc_int(array, index, newvalue, - self.memo_cast) - elif arraydescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setarrayitem_gc_float(array, index, newvalue) - else: - raise NotImplementedError + return llimpl.do_new_array(arraydescr.ofs, length) + + def bh_arraylen_gc(self, arraydescr, array): + assert isinstance(arraydescr, Descr) + return llimpl.do_arraylen_gc(arraydescr, array) + + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_int(array, index, newvalue) + + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + assert isinstance(arraydescr, Descr) + llimpl.do_setarrayitem_gc_float(array, index, newvalue) - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = structbox.getref_base() - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - else: - raise NotImplementedError + llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue) - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): assert isinstance(fielddescr, Descr) - struct = self.cast_int_to_adr(structbox.getint()) - if fielddescr.typeinfo == REF: - newvalue = newvaluebox.getref_base() - llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == INT: - newvalue = newvaluebox.getint() - llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue, - self.memo_cast) - elif fielddescr.typeinfo == FLOAT: - newvalue = newvaluebox.getfloat() - llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue, - self.memo_cast) - else: - raise NotImplementedError + llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): + assert isinstance(fielddescr, Descr) + llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue) - def do_same_as(self, box1): - return box1.clonebox() + def bh_newstr(self, length): + return llimpl.do_newstr(length) - def do_newstr(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newstr(0, length)) - - def do_newunicode(self, lengthbox): - length = lengthbox.getint() - return history.BoxPtr(llimpl.do_newunicode(0, length)) - - def do_strsetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_strsetitem(0, string, index, newvalue) - - def do_unicodesetitem(self, stringbox, indexbox, newvaluebox): - string = stringbox.getref_base() - index = indexbox.getint() - newvalue = newvaluebox.getint() - llimpl.do_unicodesetitem(0, string, index, newvalue) + def bh_newunicode(self, length): + return llimpl.do_newunicode(length) - def do_call(self, args, calldescr): - assert isinstance(calldescr, Descr) - func = args[0].getint() - for arg in args[1:]: - if arg.type == REF: - llimpl.do_call_pushptr(arg.getref_base()) - elif arg.type == FLOAT: - llimpl.do_call_pushfloat(arg.getfloat()) - else: - llimpl.do_call_pushint(arg.getint()) - if calldescr.typeinfo == REF: - return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) - elif calldescr.typeinfo == INT: - return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) - elif calldescr.typeinfo == FLOAT: - return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast)) - elif calldescr.typeinfo == 'v': # void - llimpl.do_call_void(func, self.memo_cast) - else: - raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + llimpl.do_strsetitem(string, index, newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + llimpl.do_unicodesetitem(string, index, newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(INT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_int(func) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(REF, calldescr, args_i, args_r, args_f) + return llimpl.do_call_ptr(func) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call(FLOAT, calldescr, args_i, args_r, args_f) + return llimpl.do_call_float(func) + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + self._prepare_call('v', calldescr, args_i, args_r, args_f) + llimpl.do_call_void(func) - def do_cast_ptr_to_int(self, ptrbox): - return history.BoxInt(llimpl.cast_to_int(ptrbox.getref_base(), - self.memo_cast)) + def _prepare_call(self, resulttypeinfo, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, Descr) + assert calldescr.typeinfo == resulttypeinfo + if args_i is not None: + for x in args_i: + llimpl.do_call_pushint(x) + if args_r is not None: + for x in args_r: + llimpl.do_call_pushptr(x) + if args_f is not None: + for x in args_f: + llimpl.do_call_pushfloat(x) def force(self, force_token): - token = self.cast_int_to_adr(force_token) + token = llmemory.cast_int_to_adr(force_token) frame = llimpl.get_forced_token_frame(token) fail_index = llimpl.force(frame) self.latest_frame = frame return self.get_fail_descr_from_number(fail_index) -class OOtypeCPU(BaseCPU): +class OOtypeCPU_xxx_disabled(BaseCPU): is_oo = True ts = oohelper @@ -629,7 +546,7 @@ assert isinstance(typedescr, TypeDescr) return typedescr.getarraylength(box1) - def do_call(self, args, descr): + def do_call_XXX(self, args, descr): assert isinstance(descr, StaticMethDescr) funcbox = args[0] argboxes = args[1:] @@ -842,10 +759,3 @@ def __repr__(self): return '' % self.fieldname - - -# ____________________________________________________________ - -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(LLtypeCPU) -pypy.jit.metainterp.executor.make_execute_list(OOtypeCPU) Modified: pypy/branch/fast-forward/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llgraph/test/test_llgraph.py Sun Jun 20 18:38:42 2010 @@ -7,6 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.test.runner_test import LLtypeBackendTest class TestLLTypeLLGraph(LLtypeBackendTest): @@ -18,25 +19,25 @@ def setup_method(self, _): self.cpu = self.cpu_type(None) - def test_cast_adr_to_int_and_back(self): - cpu = self.cpu - X = lltype.Struct('X', ('foo', lltype.Signed)) - x = lltype.malloc(X, immortal=True) - x.foo = 42 - a = llmemory.cast_ptr_to_adr(x) - i = cpu.cast_adr_to_int(a) - assert isinstance(i, int) - a2 = cpu.cast_int_to_adr(i) - assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x - assert cpu.cast_adr_to_int(llmemory.NULL) == 0 - assert cpu.cast_int_to_adr(0) == llmemory.NULL +def test_cast_adr_to_int_and_back(): + X = lltype.Struct('X', ('foo', lltype.Signed)) + x = lltype.malloc(X, immortal=True) + x.foo = 42 + a = llmemory.cast_ptr_to_adr(x) + i = heaptracker.adr2int(a) + assert lltype.typeOf(i) is lltype.Signed + a2 = heaptracker.int2adr(i) + assert llmemory.cast_adr_to_ptr(a2, lltype.Ptr(X)) == x + assert heaptracker.adr2int(llmemory.NULL) == 0 + assert heaptracker.int2adr(0) == llmemory.NULL ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type def test_fielddescr_ootype(): + py.test.skip("ootype tests skipped") from pypy.rpython.ootypesystem import ootype from pypy.jit.backend.llgraph.runner import OOtypeCPU A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/descr.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llsupport/descr.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/descr.py Sun Jun 20 18:38:42 2010 @@ -1,10 +1,11 @@ import py -from pypy.rpython.lltypesystem import lltype, rffi, llmemory +from pypy.rpython.lltypesystem import lltype, rffi, llmemory, rclass from pypy.jit.backend.llsupport import symbolic, support from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # The point of the class organization in this file is to make instances # as compact as possible. This is done by not storing the field size or @@ -40,6 +41,10 @@ def repr_of_descr(self): return '' % self.size +class SizeDescrWithVTable(SizeDescr): + def as_vtable_size_descr(self): + return self + BaseSizeDescr = SizeDescr def get_size_descr(gccache, STRUCT): @@ -48,7 +53,10 @@ return cache[STRUCT] except KeyError: size = symbolic.get_size(STRUCT, gccache.translate_support_code) - sizedescr = SizeDescr(size) + if heaptracker.has_gcstruct_a_vtable(STRUCT): + sizedescr = SizeDescrWithVTable(size) + else: + sizedescr = SizeDescr(size) gccache.init_size_descr(STRUCT, sizedescr) cache[STRUCT] = sizedescr return sizedescr @@ -179,7 +187,6 @@ # CallDescrs class BaseCallDescr(AbstractDescr): - empty_box = BoxInt(0) _clsname = '' loop_token = None arg_classes = '' # <-- annotation hack @@ -191,35 +198,20 @@ def get_extra_info(self): return self.extrainfo - _returns_a_pointer = False # unless overridden by GcPtrCallDescr - _returns_a_float = False # unless overridden by FloatCallDescr - _returns_a_void = False # unless overridden by VoidCallDescr - - def returns_a_pointer(self): - return self._returns_a_pointer - - def returns_a_float(self): - return self._returns_a_float + def get_arg_types(self): + return self.arg_classes - def returns_a_void(self): - return self._returns_a_void + def get_return_type(self): + return self._return_type def get_result_size(self, translate_support_code): raise NotImplementedError - def get_call_stub(self): - return self.call_stub - def create_call_stub(self, rtyper, RESULT): - def process(no, c): - if c == 'i': - return 'args[%d].getint()' % (no,) - elif c == 'f': - return 'args[%d].getfloat()' % (no,) - elif c == 'r': - return 'args[%d].getref_base()' % (no,) - else: - raise Exception("Unknown type %s for type %s" % (c, TP)) + def process(c): + arg = 'args_%s[%d]' % (c, seen[c]) + seen[c] += 1 + return arg def TYPE(arg): if arg == 'i': @@ -230,21 +222,23 @@ return llmemory.GCREF elif arg == 'v': return lltype.Void - - args = ", ".join([process(i + 1, c) for i, c in - enumerate(self.arg_classes)]) - - if self.returns_a_pointer(): - result = 'history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, res))' - elif self.returns_a_float(): - result = 'history.BoxFloat(res)' - elif self.returns_a_void(): + + seen = {'i': 0, 'r': 0, 'f': 0} + args = ", ".join([process(c) for c in self.arg_classes]) + + if self.get_return_type() == history.INT: + result = 'rffi.cast(lltype.Signed, res)' + elif self.get_return_type() == history.REF: + result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)' + elif self.get_return_type() == history.FLOAT: + result = 'res' + elif self.get_return_type() == history.VOID: result = 'None' else: - result = 'history.BoxInt(rffi.cast(lltype.Signed, res))' + assert 0 source = py.code.Source(""" - def call_stub(args): - fnptr = rffi.cast(lltype.Ptr(FUNC), args[0].getint()) + def call_stub(func, args_i, args_r, args_f): + fnptr = rffi.cast(lltype.Ptr(FUNC), func) res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s) return %(result)s """ % locals()) @@ -255,35 +249,64 @@ exec source.compile() in d self.call_stub = d['call_stub'] + def verify_types(self, args_i, args_r, args_f, return_type): + assert self._return_type == return_type + assert self.arg_classes.count('i') == len(args_i or ()) + assert self.arg_classes.count('r') == len(args_r or ()) + assert self.arg_classes.count('f') == len(args_f or ()) + def repr_of_descr(self): return '<%s>' % self._clsname -class NonGcPtrCallDescr(BaseCallDescr): +class BaseIntCallDescr(BaseCallDescr): + # Base class of the various subclasses of descrs corresponding to + # calls having a return kind of 'int' (including non-gc pointers). + # The inheritance hierarchy is a bit different than with other Descr + # classes because of the 'call_stub' attribute, which is of type + # + # lambda func, args_i, args_r, args_f --> int/ref/float/void + # + # The purpose of BaseIntCallDescr is to be the parent of all classes + # in which 'call_stub' has a return kind of 'int'. + _return_type = history.INT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0) + +class NonGcPtrCallDescr(BaseIntCallDescr): _clsname = 'NonGcPtrCallDescr' - def get_result_size(self, translate_support_code): return symbolic.get_size_of_ptr(translate_support_code) -class GcPtrCallDescr(NonGcPtrCallDescr): - empty_box = BoxPtr(lltype.nullptr(llmemory.GCREF.TO)) +class GcPtrCallDescr(BaseCallDescr): _clsname = 'GcPtrCallDescr' - _returns_a_pointer = True + _return_type = history.REF + call_stub = staticmethod(lambda func, args_i, args_r, args_f: + lltype.nullptr(llmemory.GCREF.TO)) + def get_result_size(self, translate_support_code): + return symbolic.get_size_of_ptr(translate_support_code) + +class FloatCallDescr(BaseCallDescr): + _clsname = 'FloatCallDescr' + _return_type = history.FLOAT + call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0.0) + def get_result_size(self, translate_support_code): + return symbolic.get_size(lltype.Float, translate_support_code) -class VoidCallDescr(NonGcPtrCallDescr): - empty_box = None +class VoidCallDescr(BaseCallDescr): _clsname = 'VoidCallDescr' - _returns_a_void = True - + _return_type = history.VOID + call_stub = staticmethod(lambda func, args_i, args_r, args_f: None) def get_result_size(self, translate_support_code): return 0 def getCallDescrClass(RESULT): if RESULT is lltype.Void: return VoidCallDescr - return getDescrClass(RESULT, BaseCallDescr, GcPtrCallDescr, + if RESULT is lltype.Float: + return FloatCallDescr + return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr, NonGcPtrCallDescr, 'Call', 'get_result_size', - '_returns_a_float') + Ellipsis) # <= floatattrname should not be used here def get_call_descr(gccache, ARGS, RESULT, extrainfo=None): arg_classes = [] @@ -330,7 +353,6 @@ # if TYPE is lltype.Float: setattr(Descr, floatattrname, True) - Descr.empty_box = BoxFloat(0.0) # _cache[nameprefix, TYPE] = Descr return Descr Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py Sun Jun 20 18:38:42 2010 @@ -170,7 +170,7 @@ # first look in the hashtable, using an inexact hash (fails after # the object moves) addr = llmemory.cast_ptr_to_adr(gcref) - hash = llmemory.cast_adr_to_int(addr) + hash = llmemory.cast_adr_to_int(addr, "forced") hash -= hash >> self.HASHTABLE_BITS hash &= self.HASHTABLE_SIZE - 1 addr_ref = self.hashtable[hash] Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py Sun Jun 20 18:38:42 2010 @@ -6,16 +6,19 @@ from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\ BoxFloat +from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.model import AbstractCPU 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, BaseSizeDescr from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr -from pypy.jit.backend.llsupport.descr import get_call_descr, BaseCallDescr +from pypy.jit.backend.llsupport.descr import get_call_descr +from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr +from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr from pypy.rpython.annlowlevel import cast_instance_to_base_ptr -empty_int_box = BoxInt(0) class AbstractLLCPU(AbstractCPU): from pypy.jit.metainterp.typesystem import llhelper as ts @@ -47,7 +50,7 @@ self._setup_exception_handling_translated() else: self._setup_exception_handling_untranslated() - self.clear_exception() + self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) self.setup() if translate_support_code: self._setup_on_leave_jitted_translated() @@ -57,9 +60,6 @@ def setup(self): pass - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case bk = self.rtyper.annotator.bookkeeper @@ -104,12 +104,10 @@ def save_exception(): # copy from _exception_emulator to the real attributes on self - tp_i = _exception_emulator[0] - v_i = _exception_emulator[1] + v_i = _exception_emulator[1] _exception_emulator[0] = 0 _exception_emulator[1] = 0 - self.saved_exception = tp_i - self.saved_exc_value = self._cast_int_to_gcref(v_i) + self.saved_exc_value = rffi.cast(llmemory.GCREF, v_i) self.pos_exception = pos_exception self.pos_exc_value = pos_exc_value @@ -120,15 +118,14 @@ def pos_exception(): addr = llop.get_exception_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) - return llmemory.cast_adr_to_int(addr) + return heaptracker.adr2int(addr) def save_exception(): addr = llop.get_exception_addr(llmemory.Address) - exception = rffi.cast(lltype.Signed, addr.address[0]) addr.address[0] = llmemory.NULL addr = llop.get_exc_value_addr(llmemory.Address) exc_value = rffi.cast(llmemory.GCREF, addr.address[0]) @@ -136,7 +133,6 @@ # from now on, the state is again consistent -- no more RPython # exception is set. The following code produces a write barrier # in the assignment to self.saved_exc_value, as needed. - self.saved_exception = exception self.saved_exc_value = exc_value self.pos_exception = pos_exception @@ -174,16 +170,10 @@ f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc) return rffi.cast(lltype.Signed, f) - def get_exception(self): - return self.saved_exception - - def get_exc_value(self): - return self.saved_exc_value - - def clear_exception(self): - self.saved_exception = 0 + def grab_exc_value(self): + exc = self.saved_exc_value self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO) - + return exc # ------------------- helpers and descriptions -------------------- @@ -213,24 +203,30 @@ def unpack_fielddescr(self, fielddescr): assert isinstance(fielddescr, BaseFieldDescr) + return fielddescr.offset + unpack_fielddescr._always_inline_ = True + + def unpack_fielddescr_size(self, fielddescr): + assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset size = fielddescr.get_field_size(self.translate_support_code) - ptr = fielddescr.is_pointer_field() - float = fielddescr.is_float_field() - return ofs, size, ptr, float - unpack_fielddescr._always_inline_ = True + return ofs, size + unpack_fielddescr_size._always_inline_ = True def arraydescrof(self, A): return get_array_descr(self.gc_ll_descr, A) def unpack_arraydescr(self, arraydescr): assert isinstance(arraydescr, BaseArrayDescr) + return arraydescr.get_base_size(self.translate_support_code) + unpack_arraydescr._always_inline_ = True + + def unpack_arraydescr_size(self, arraydescr): + assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_base_size(self.translate_support_code) size = arraydescr.get_item_size(self.translate_support_code) - ptr = arraydescr.is_array_of_pointers() - float = arraydescr.is_array_of_floats() - return ofs, size, ptr, float - unpack_arraydescr._always_inline_ = True + return ofs, size + unpack_arraydescr_size._always_inline_ = True def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None): return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo) @@ -249,254 +245,222 @@ # ____________________________________________________________ - def do_arraylen_gc(self, arraybox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): assert isinstance(arraydescr, BaseArrayDescr) ofs = arraydescr.get_ofs_length(self.translate_support_code) - gcref = arraybox.getref_base() - length = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] - return BoxInt(length) - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) + return rffi.cast(rffi.CArrayPtr(lltype.Signed), array)[ofs/WORD] + + def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex): + ofs, size = self.unpack_arraydescr_size(arraydescr) # --- start of GC unsafe code (no GC operation!) --- items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - pval = self._cast_int_to_gcref(items[itemindex]) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - fval = items[itemindex] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: items = rffi.cast(rffi.CArrayPtr(TYPE), items) val = items[itemindex] # --- end of GC unsafe code --- - return BoxInt(rffi.cast(lltype.Signed, val)) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_setarrayitem_gc(self, arraybox, indexbox, vbox, arraydescr): - itemindex = indexbox.getint() - gcref = arraybox.getref_base() - ofs, size, ptr, float = self.unpack_arraydescr(arraydescr) - # - if ptr: - vboxptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, vboxptr) - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) - items[itemindex] = self.cast_gcref_to_int(vboxptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) - items[itemindex] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def bh_getarrayitem_gc_r(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + pval = self._cast_int_to_gcref(items[itemindex]) + # --- end of GC unsafe code --- + return pval + + def bh_getarrayitem_gc_f(self, arraydescr, gcref, itemindex): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + fval = items[itemindex] + # --- end of GC unsafe code --- + return fval + + def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue): + ofs, size = self.unpack_arraydescr_size(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) items = rffi.cast(rffi.CArrayPtr(TYPE), items) - items[itemindex] = rffi.cast(TYPE, val) + items[itemindex] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def _new_do_len(TP): - def do_strlen(self, stringbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(TP, - self.translate_support_code) - gcref = stringbox.getref_base() - v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] - return BoxInt(v) - return do_strlen - - do_strlen = _new_do_len(rstr.STR) - do_unicodelen = _new_do_len(rstr.UNICODE) - - def do_strgetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] - return BoxInt(ord(v)) - - def do_unicodegetitem(self, stringbox, indexbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - gcref = stringbox.getref_base() - i = indexbox.getint() - basesize = basesize // itemsize - v = rffi.cast(rffi.CArrayPtr(lltype.UniChar), gcref)[basesize + i] - return BoxInt(ord(v)) + def bh_setarrayitem_gc_r(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + self.gc_ll_descr.do_write_barrier(gcref, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items) + items[itemindex] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- + + def bh_setarrayitem_gc_f(self, arraydescr, gcref, itemindex, newvalue): + ofs = self.unpack_arraydescr(arraydescr) + # --- start of GC unsafe code (no GC operation!) --- + items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) + items = rffi.cast(rffi.CArrayPtr(lltype.Float), items) + items[itemindex] = newvalue + # --- end of GC unsafe code --- + + def bh_strlen(self, string): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return len(s.chars) + + def bh_unicodelen(self, string): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return len(u.chars) + + def bh_strgetitem(self, string, index): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return ord(s.chars[index]) + + def bh_unicodegetitem(self, string, index): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + return ord(u.chars[index]) @specialize.argtype(1) - def _base_do_getfield(self, gcref, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) + def _base_do_getfield_i(self, struct, fielddescr): + ofs, size = self.unpack_fielddescr_size(fielddescr) # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - # - if ptr: - pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), field)[0] - pval = self._cast_int_to_gcref(pval) - # --- end of GC unsafe code --- - return BoxPtr(pval) - # - if float: - fval = rffi.cast(rffi.CArrayPtr(lltype.Float), field)[0] - # --- end of GC unsafe code --- - return BoxFloat(fval) - # + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - val = rffi.cast(rffi.CArrayPtr(TYPE), field)[0] + val = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)[0] # --- end of GC unsafe code --- - val = rffi.cast(lltype.Signed, val) - return BoxInt(val) + return rffi.cast(lltype.Signed, val) else: raise NotImplementedError("size = %d" % size) - def do_getfield_gc(self, structbox, fielddescr): - gcref = structbox.getref_base() - return self._base_do_getfield(gcref, fielddescr) + @specialize.argtype(1) + def _base_do_getfield_r(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0] + pval = self._cast_int_to_gcref(pval) + # --- end of GC unsafe code --- + return pval - def do_getfield_raw(self, structbox, fielddescr): - return self._base_do_getfield(structbox.getint(), fielddescr) + @specialize.argtype(1) + def _base_do_getfield_f(self, struct, fielddescr): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fval = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr)[0] + # --- end of GC unsafe code --- + return fval + + bh_getfield_gc_i = _base_do_getfield_i + bh_getfield_gc_r = _base_do_getfield_r + bh_getfield_gc_f = _base_do_getfield_f + bh_getfield_raw_i = _base_do_getfield_i + bh_getfield_raw_r = _base_do_getfield_r + bh_getfield_raw_f = _base_do_getfield_f @specialize.argtype(1) - def _base_do_setfield(self, gcref, vbox, fielddescr): - ofs, size, ptr, float = self.unpack_fielddescr(fielddescr) - # - if ptr: - assert lltype.typeOf(gcref) is not lltype.Signed, ( - "can't handle write barriers for setfield_raw") - ptr = vbox.getref_base() - self.gc_ll_descr.do_write_barrier(gcref, ptr) - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Signed), field) - field[0] = self.cast_gcref_to_int(ptr) - # --- end of GC unsafe code --- - return - # - if float: - fval = vbox.getfloat() - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(lltype.Float), field) - field[0] = fval - # --- end of GC unsafe code --- - return - # - val = vbox.getint() + def _base_do_setfield_i(self, struct, fielddescr, newvalue): + ofs, size = self.unpack_fielddescr_size(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) for TYPE, itemsize in unroll_basic_sizes: if size == itemsize: - # --- start of GC unsafe code (no GC operation!) --- - field = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs) - field = rffi.cast(rffi.CArrayPtr(TYPE), field) - field[0] = rffi.cast(TYPE, val) + fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr) + fieldptr[0] = rffi.cast(TYPE, newvalue) # --- end of GC unsafe code --- return else: raise NotImplementedError("size = %d" % size) - def do_setfield_gc(self, structbox, vbox, fielddescr): - gcref = structbox.getref_base() - self._base_do_setfield(gcref, vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_r(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + assert lltype.typeOf(struct) is not lltype.Signed, ( + "can't handle write barriers for setfield_raw") + self.gc_ll_descr.do_write_barrier(struct, newvalue) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr) + fieldptr[0] = self.cast_gcref_to_int(newvalue) + # --- end of GC unsafe code --- - def do_setfield_raw(self, structbox, vbox, fielddescr): - self._base_do_setfield(structbox.getint(), vbox, fielddescr) + @specialize.argtype(1) + def _base_do_setfield_f(self, struct, fielddescr, newvalue): + ofs = self.unpack_fielddescr(fielddescr) + # --- start of GC unsafe code (no GC operation!) --- + fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs) + fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Float), fieldptr) + fieldptr[0] = newvalue + # --- end of GC unsafe code --- + + bh_setfield_gc_i = _base_do_setfield_i + bh_setfield_gc_r = _base_do_setfield_r + bh_setfield_gc_f = _base_do_setfield_f + bh_setfield_raw_i = _base_do_setfield_i + bh_setfield_raw_r = _base_do_setfield_r + bh_setfield_raw_f = _base_do_setfield_f - def do_new(self, sizedescr): - res = self.gc_ll_descr.gc_malloc(sizedescr) - return BoxPtr(res) + def bh_new(self, sizedescr): + return self.gc_ll_descr.gc_malloc(sizedescr) - def do_new_with_vtable(self, classbox): - classint = classbox.getint() - descrsize = self.class_sizes[classint] - res = self.gc_ll_descr.gc_malloc(descrsize) + def bh_new_with_vtable(self, sizedescr, vtable): + res = self.gc_ll_descr.gc_malloc(sizedescr) if self.vtable_offset is not None: as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res) - as_array[self.vtable_offset/WORD] = classint - return BoxPtr(res) + as_array[self.vtable_offset/WORD] = vtable + return res - def do_new_array(self, countbox, arraydescr): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem) - return BoxPtr(res) - - def do_newstr(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_str(num_elem) - return BoxPtr(res) - - def do_newunicode(self, countbox): - num_elem = countbox.getint() - res = self.gc_ll_descr.gc_malloc_unicode(num_elem) - return BoxPtr(res) - - def do_strsetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) - - def do_unicodesetitem(self, stringbox, indexbox, vbox): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.translate_support_code) - index = indexbox.getint() - v = vbox.getint() - a = stringbox.getref_base() - basesize = basesize // itemsize - rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v) - - def do_call(self, args, calldescr): - assert isinstance(calldescr, BaseCallDescr) - assert len(args) == 1 + len(calldescr.arg_classes) + def bh_classof(self, struct): + struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) + result = struct.typeptr + result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) + return heaptracker.adr2int(result_adr) + + def bh_new_array(self, arraydescr, length): + return self.gc_ll_descr.gc_malloc_array(arraydescr, length) + + def bh_newstr(self, length): + return self.gc_ll_descr.gc_malloc_str(length) + + def bh_newunicode(self, length): + return self.gc_ll_descr.gc_malloc_unicode(length) + + def bh_strsetitem(self, string, index, newvalue): + s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + s.chars[index] = chr(newvalue) + + def bh_unicodesetitem(self, string, index, newvalue): + u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string) + u.chars[index] = unichr(newvalue) + + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, BaseIntCallDescr) if not we_are_translated(): - assert (list(calldescr.arg_classes) == - [arg.type for arg in args[1:]]) - callstub = calldescr.get_call_stub() - try: - return callstub(args) - except Exception, e: - if not we_are_translated(): - if not type(e) is LLException: - raise - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - e.args[1]) - self.saved_exception = rffi.cast(lltype.Signed, e.args[0]) - else: - ptr = cast_instance_to_base_ptr(e) - self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF, - ptr) - self.saved_exception = rffi.cast(lltype.Signed, ptr.typeptr) - return calldescr.empty_box - - def do_cast_ptr_to_int(self, ptrbox): - return BoxInt(self.cast_gcref_to_int(ptrbox.getref_base())) + calldescr.verify_types(args_i, args_r, args_f, history.INT) + return calldescr.call_stub(func, args_i, args_r, args_f) + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, GcPtrCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.REF) + return calldescr.call_stub(func, args_i, args_r, args_f) -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU) + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, FloatCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.FLOAT) + return calldescr.call_stub(func, args_i, args_r, args_f) + + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): + assert isinstance(calldescr, VoidCallDescr) + if not we_are_translated(): + calldescr.verify_types(args_i, args_r, args_f, history.VOID) + return calldescr.call_stub(func, args_i, args_r, args_f) Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_descr.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_descr.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_descr.py Sun Jun 20 18:38:42 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr +from pypy.jit.metainterp import history def test_get_size_descr(): c0 = GcCache(False) @@ -145,33 +146,29 @@ c0 = GcCache(False) descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char) assert descr1.get_result_size(False) == rffi.sizeof(lltype.Char) - assert not descr1.returns_a_pointer() - assert not descr1.returns_a_float() + assert descr1.get_return_type() == history.INT assert descr1.arg_classes == "ii" - assert isinstance(descr1.empty_box, BoxInt) # T = lltype.GcStruct('T') descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T)) assert descr2.get_result_size(False) == rffi.sizeof(lltype.Ptr(T)) - assert descr2.returns_a_pointer() - assert not descr2.returns_a_float() + assert descr2.get_return_type() == history.REF assert descr2.arg_classes == "r" - assert isinstance(descr2.empty_box, BoxPtr) # U = lltype.GcStruct('U', ('x', lltype.Signed)) assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U)) # V = lltype.Struct('V', ('x', lltype.Signed)) - assert isinstance(get_call_descr(c0, [], lltype.Ptr(V)).empty_box, BoxInt) + assert (get_call_descr(c0, [], lltype.Ptr(V)).get_return_type() == + history.INT) # - assert get_call_descr(c0, [], lltype.Void).empty_box is None + assert (get_call_descr(c0, [], lltype.Void).get_return_type() == + history.VOID) # descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float) assert descr4.get_result_size(False) == rffi.sizeof(lltype.Float) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" - assert isinstance(descr4.empty_box, BoxFloat) def test_get_call_descr_translated(): c1 = GcCache(True) @@ -179,14 +176,12 @@ U = lltype.GcStruct('U', ('x', lltype.Signed)) descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U)) assert isinstance(descr3.get_result_size(True), Symbolic) - assert descr3.returns_a_pointer() - assert not descr3.returns_a_float() + assert descr3.get_return_type() == history.REF assert descr3.arg_classes == "r" # descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float) assert isinstance(descr4.get_result_size(True), Symbolic) - assert not descr4.returns_a_pointer() - assert descr4.returns_a_float() + assert descr4.get_return_type() == history.FLOAT assert descr4.arg_classes == "ff" def test_call_descr_extra_info(): @@ -245,12 +240,11 @@ def f(a, b): return 'c' - call_stub = descr1.get_call_stub() + call_stub = descr1.call_stub fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) - res = call_stub([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxInt(1), BoxInt(2)]) - assert res.getint() == ord('c') + res = call_stub(rffi.cast(lltype.Signed, fnptr), [1, 2], None, None) + assert res == ord('c') ARRAY = lltype.GcArray(lltype.Signed) ARGS = [lltype.Float, lltype.Ptr(ARRAY)] @@ -264,6 +258,6 @@ a = lltype.malloc(ARRAY, 3) opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a) a[0] = 1 - res = descr2.get_call_stub()([BoxInt(rffi.cast(lltype.Signed, fnptr)), - BoxFloat(3.5), BoxPtr(opaquea)]) - assert res.getfloat() == 4.5 + res = descr2.call_stub(rffi.cast(lltype.Signed, fnptr), + [], [opaquea], [3.5]) + assert res == 4.5 Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py Sun Jun 20 18:38:42 2010 @@ -291,7 +291,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -303,7 +303,7 @@ assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) - assert operations[1].opnum == rop.OOIS + assert operations[1].opnum == rop.PTR_EQ assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result @@ -324,7 +324,7 @@ v_random_box = BoxPtr() v_result = BoxInt() operations = [ - ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], + ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr @@ -336,7 +336,7 @@ finally: rgc.can_move = old_can_move assert len(operations) == 1 - assert operations[0].opnum == rop.OOIS + assert operations[0].opnum == rop.PTR_EQ assert operations[0].args == [v_random_box, ConstPtr(s_gcref)] assert operations[0].result == v_result # check that s_gcref gets added to the list anyway, to make sure Modified: pypy/branch/fast-forward/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/model.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/model.py Sun Jun 20 18:38:42 2010 @@ -3,10 +3,14 @@ class AbstractCPU(object): supports_floats = False + _got_exception = None # assembler_helper_ptr - a pointer to helper to call after a direct # assembler call portal_calldescr = None + done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 + done_with_this_frame_ref_v = -1 + done_with_this_frame_float_v = -1 def __init__(self): self.fail_descr_list = [] @@ -24,9 +28,6 @@ def get_fail_descr_from_number(self, n): return self.fail_descr_list[n] - def set_class_sizes(self, class_sizes): - self.class_sizes = class_sizes - def setup_once(self): """Called once by the front-end when the program starts.""" pass @@ -87,30 +88,27 @@ or from 'args' if it was a FINISH). Returns a ptr or an obj.""" raise NotImplementedError + def get_latest_value_count(self): + """Return how many values are ready to be returned by + get_latest_value_xxx(). Only after a guard failure; not + necessarily correct after a FINISH.""" + raise NotImplementedError + def get_latest_force_token(self): """After a GUARD_NOT_FORCED fails, this function returns the same FORCE_TOKEN result as the one in the just-failed loop.""" raise NotImplementedError - def make_boxes_from_latest_value(self, faildescr): - """Build a list of Boxes (and None for holes) that contains - the current values, as would be returned by calls to - get_latest_value_xxx().""" - raise NotImplementedError - - def get_exception(self): - raise NotImplementedError - - def get_exc_value(self): - raise NotImplementedError - - def clear_exception(self): - raise NotImplementedError - - def get_overflow_error(self): + def clear_latest_values(self, count): + """Clear the latest values (at least the ref ones), so that + they no longer keep objects alive. 'count' is the number of + values -- normally get_latest_value_count().""" raise NotImplementedError - def get_zero_division_error(self): + def grab_exc_value(self): + """Return and clear the exception set by the latest execute_token(), + when it exits due to a failure of a GUARD_EXCEPTION or + GUARD_NO_EXCEPTION. (Returns a GCREF)""" # XXX remove me raise NotImplementedError @staticmethod @@ -118,10 +116,6 @@ raise NotImplementedError @staticmethod - def numof(S): - raise NotImplementedError - - @staticmethod def fielddescrof(S, fieldname): """Return the Descr corresponding to field 'fieldname' on the structure 'S'. It is important that this function (at least) @@ -157,101 +151,87 @@ # lltype specific operations # -------------------------- - - def do_arraylen_gc(self, arraybox, arraydescr): - raise NotImplementedError - def do_strlen(self, stringbox): + def bh_getarrayitem_gc_i(self, arraydescr, array, index): raise NotImplementedError - - def do_strgetitem(self, stringbox, indexbox): + def bh_getarrayitem_gc_r(self, arraydescr, array, index): raise NotImplementedError - - def do_unicodelen(self, stringbox): + def bh_getarrayitem_gc_f(self, arraydescr, array, index): raise NotImplementedError - def do_unicodegetitem(self, stringbox, indexbox): + def bh_getfield_gc_i(self, struct, fielddescr): raise NotImplementedError - - def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr): + def bh_getfield_gc_r(self, struct, fielddescr): + raise NotImplementedError + def bh_getfield_gc_f(self, struct, fielddescr): raise NotImplementedError - def do_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): - return self.do_call([fnptr, sourcebox, destbox, source_startbox, - dest_startbox, lengthbox], calldescr) - - def do_getfield_gc(self, structbox, fielddescr): + def bh_getfield_raw_i(self, struct, fielddescr): raise NotImplementedError - - def do_getfield_raw(self, structbox, fielddescr): + def bh_getfield_raw_r(self, struct, fielddescr): raise NotImplementedError - - def do_new(self, sizedescr): + def bh_getfield_raw_f(self, struct, fielddescr): raise NotImplementedError - def do_new_with_vtable(self, classbox): + def bh_new(self, sizedescr): + raise NotImplementedError + def bh_new_with_vtable(self, sizedescr, vtable): raise NotImplementedError - - def do_new_array(self, lengthbox, arraydescr): + def bh_new_array(self, arraydescr, length): raise NotImplementedError - - def do_setarrayitem_gc(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_newstr(self, length): + raise NotImplementedError + def bh_newunicode(self, length): raise NotImplementedError - def do_setarrayitem_raw(self, arraybox, indexbox, newvaluebox, arraydescr): + def bh_arraylen_gc(self, arraydescr, array): raise NotImplementedError - def do_setfield_gc(self, structbox, newvaluebox, fielddescr): + def bh_classof(self, struct): raise NotImplementedError - def do_setfield_raw(self, structbox, newvaluebox, fielddescr): + def bh_setarrayitem_gc_i(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newstr(self, lengthbox): + def bh_setarrayitem_gc_r(self, arraydescr, array, index, newvalue): raise NotImplementedError - - def do_newunicode(self, lengthbox): + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): raise NotImplementedError - def do_strsetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_unicodesetitem(self, stringbox, indexbox, charbox): + def bh_setfield_gc_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call(self, args, calldescr): + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_assembler(self, args, token): + def bh_setfield_raw_i(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_call_loopinvariant(self, args, calldescr): - return self.do_call(args, calldescr) - - def do_cond_call_gc_wb(self, args, calldescr): + def bh_setfield_raw_r(self, struct, fielddescr, newvalue): raise NotImplementedError - - def do_cast_ptr_to_int(self, ptrbox): + def bh_setfield_raw_f(self, struct, fielddescr, newvalue): raise NotImplementedError - def do_call_may_force(self, args, calldescr): - return self.do_call(args, calldescr) - - def force(self, force_token): + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - # ootype specific operations - # -------------------------- - - def do_runtimenew(self, classbox): + def bh_call_r(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - - def do_oosend(self, args, descr): + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + raise NotImplementedError + def bh_call_v(self, func, calldescr, args_i, args_r, args_f): raise NotImplementedError - def do_instanceof(self, instancebox, typedescr): + def bh_strlen(self, string): + raise NotImplementedError + def bh_strgetitem(self, string, index): + raise NotImplementedError + def bh_unicodelen(self, string): + raise NotImplementedError + def bh_unicodegetitem(self, string, index): + raise NotImplementedError + def bh_strsetitem(self, string, index, newvalue): + raise NotImplementedError + def bh_unicodesetitem(self, string, index, newvalue): raise NotImplementedError - def typedescr2classbox(self, descr): + def force(self, force_token): raise NotImplementedError Modified: pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py Sun Jun 20 18:38:42 2010 @@ -13,6 +13,8 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException +from pypy.jit.codewriter import heaptracker + class Runner(object): @@ -236,7 +238,7 @@ res = self.cpu.get_latest_value_int(0) assert res == 20 - def test_make_boxes_from_latest_values(self): + def test_get_latest_value_count(self): i0 = BoxInt() i1 = BoxInt() i2 = BoxInt() @@ -255,12 +257,12 @@ self.cpu.set_future_value_int(0, 2) fail = self.cpu.execute_token(looptoken) assert fail is faildescr1 - boxes = self.cpu.make_boxes_from_latest_values(faildescr1) - assert len(boxes) == 3 - assert boxes[0] is None - assert isinstance(boxes[1], BoxInt) - assert boxes[1].value == 10 - assert boxes[2] is None + + count = self.cpu.get_latest_value_count() + assert count == 3 + assert self.cpu.get_latest_value_int(1) == 10 + assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok + self.cpu.clear_latest_values(3) def test_finish(self): i0 = BoxInt() @@ -375,8 +377,8 @@ looptoken = LoopToken() self.cpu.compile_loop([v1, v2], ops, looptoken) for x, y, z in testcases: - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) fail = self.cpu.execute_token(looptoken) @@ -386,13 +388,13 @@ assert fail.identifier == 2 if z != boom: assert self.cpu.get_latest_value_int(0) == z - assert not self.cpu.get_exception() - assert not self.cpu.get_exc_value() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_ovf_operations_reversed(self): self.test_ovf_operations(reversed=True) - def test_do_call(self): + def test_bh_call(self): cpu = self.cpu # def func(c): @@ -400,24 +402,21 @@ FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxInt(ord('A'))], - calldescr) - assert x.value == ord('B') + x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value, + calldescr, [ord('A')], None, None) + assert x == ord('B') if cpu.supports_floats: def func(f, i): - return float(i) + f + return f - float(i) FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed], lltype.Float)) func_ptr = llhelper(FPTR, func) FTP = deref(FPTR) calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT) - x = cpu.do_call( - [self.get_funcbox(cpu, func_ptr), - BoxFloat(3.5), BoxInt(42)], - calldescr) - assert x.value == 42 + 3.5 + x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value, + calldescr, + [42], None, [3.5]) + assert x == 3.5 - 42 def test_call(self): @@ -611,31 +610,31 @@ def test_ooops(self): u1_box, U_box = self.alloc_instance(self.U) u2_box, U_box = self.alloc_instance(self.U) - r = self.execute_operation(rop.OOIS, [u1_box, - u1_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, + u1_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [u2_box, - u2_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, + u2_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [u1_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int') assert r.value == 1 # null_box = self.null_instance() - r = self.execute_operation(rop.OOIS, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, + null_box.clonebox()], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOIS, [u1_box, null_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOIS, [null_box, u2_box], 'int') + r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [null_box, - null_box.clonebox()], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, + null_box.clonebox()], 'int') assert r.value == 0 - r = self.execute_operation(rop.OOISNOT, [u2_box, null_box], 'int') + r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [null_box, u1_box], 'int') + r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int') assert r.value == 1 def test_array_basic(self): @@ -768,10 +767,10 @@ assert r.value == 153 def test_do_unicode_basic(self): - u_box = self.cpu.do_newunicode(ConstInt(5)) - self.cpu.do_unicodesetitem(u_box, BoxInt(4), BoxInt(123)) - r = self.cpu.do_unicodegetitem(u_box, BoxInt(4)) - assert r.value == 123 + u = self.cpu.bh_newunicode(5) + self.cpu.bh_unicodesetitem(u, 4, 123) + r = self.cpu.bh_unicodegetitem(u, 4) + assert r == 123 def test_unicode_basic(self): u_box = self.alloc_unicode(u"hello\u1234") @@ -808,17 +807,10 @@ assert r.value == 5.5 def test_virtual_ref(self): - # if VIRTUAL_REF reaches the backend, it should just be a SAME_AS - u_box = self.alloc_unicode(u"hello\u1234") - r = self.execute_operation(rop.VIRTUAL_REF, [u_box, ConstInt(2)], - 'ref') - assert r.value == u_box.value + pass # VIRTUAL_REF must not reach the backend nowadays def test_virtual_ref_finish(self): - # if VIRTUAL_REF_FINISH reaches the backend, it is a no-op - self.execute_operation(rop.VIRTUAL_REF_FINISH, - [BoxInt(123), BoxInt(234)], - 'void') + pass # VIRTUAL_REF_FINISH must not reach the backend nowadays def test_jump(self): # this test generates small loops where the JUMP passes many @@ -1082,7 +1074,6 @@ operator.truediv, no_zero_divison yield nan_and_infinity, rop.FLOAT_NEG, operator.neg, all_cases_unary yield nan_and_infinity, rop.FLOAT_ABS, abs, all_cases_unary - yield nan_and_infinity, rop.FLOAT_IS_TRUE, bool, all_cases_unary yield nan_and_infinity, rop.FLOAT_LT, operator.lt, all_cases_binary yield nan_and_infinity, rop.FLOAT_LE, operator.le, all_cases_binary yield nan_and_infinity, rop.FLOAT_EQ, operator.eq, all_cases_binary @@ -1102,7 +1093,7 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): addr = llmemory.cast_ptr_to_adr(func_ptr) - return BoxInt(cpu.cast_adr_to_int(addr)) + return ConstInt(heaptracker.adr2int(addr)) MY_VTABLE = rclass.OBJECT_VTABLE # for tests only @@ -1134,7 +1125,7 @@ elif T == self.U: t.parent.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) + T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr)) return t_box, T_box def null_instance(self): @@ -1163,23 +1154,26 @@ def test_casts(self): + py.test.skip("xxx fix or kill") from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') x = lltype.malloc(TP) x = lltype.cast_opaque_ptr(llmemory.GCREF, x) res = self.execute_operation(rop.CAST_PTR_TO_INT, [BoxPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) res = self.execute_operation(rop.CAST_PTR_TO_INT, [ConstPtr(x)], 'int').value - assert res == self.cpu.cast_gcref_to_int(x) + expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + assert rffi.get_real_int(res) == rffi.get_real_int(expected) def test_ooops_non_gc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) - r = self.execute_operation(rop.OOIS, [BoxInt(v), BoxInt(v)], 'int') + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) + r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 1 - r = self.execute_operation(rop.OOISNOT, [BoxInt(v), BoxInt(v)], 'int') + r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int') assert r.value == 0 lltype.free(x, flavor='raw') @@ -1206,7 +1200,7 @@ S = lltype.Struct('S', ('x', lltype.Signed)) s = lltype.malloc(S, flavor='raw') sa = llmemory.cast_ptr_to_adr(s) - s_box = BoxInt(self.cpu.cast_adr_to_int(sa)) + s_box = BoxInt(heaptracker.adr2int(sa)) for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW), (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)): fd = self.cpu.fielddescrof(S, 'x') @@ -1218,7 +1212,9 @@ def test_new_with_vtable(self): cpu = self.cpu t_box, T_box = self.alloc_instance(self.T) - cpu.set_class_sizes({T_box.value: cpu.sizeof(self.T)}) + vtable = llmemory.cast_adr_to_ptr( + llmemory.cast_int_to_adr(T_box.value), heaptracker.VTABLETYPE) + heaptracker.register_known_gctype(cpu, vtable, self.T) r1 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') r2 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref') assert r1.value != r2.value @@ -1234,11 +1230,11 @@ s = lltype.cast_opaque_ptr(lltype.Ptr(self.T), r1.value) assert s.parent.chr1 == chr(190) assert s.parent.chr2 == chr(150) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1313 - self.cpu.do_setfield_gc(r1, BoxInt(1333), descrshort) - r = self.cpu.do_getfield_gc(r1, descrshort) - assert r.value == 1333 + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1313 + self.cpu.bh_setfield_gc_i(r1.value, descrshort, 1333) + r = self.cpu.bh_getfield_gc_i(r1.value, descrshort) + assert r == 1333 r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int', descr=descrshort) assert r.value == 1333 @@ -1305,11 +1301,13 @@ self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 assert self.cpu.get_latest_value_ref(1) == xptr - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) ytp.subclassrange_min = 2 @@ -1327,7 +1325,9 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == yptr + assert not self.cpu.grab_exc_value() # cleared exc_tp = xtp exc_ptr = xptr @@ -1343,11 +1343,13 @@ self.cpu.set_future_value_int(0, 1) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 1 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert excvalue == xptr self.cpu.set_future_value_int(0, 0) self.cpu.execute_token(loop.token) assert self.cpu.get_latest_value_int(0) == 0 - self.cpu.clear_exception() + excvalue = self.cpu.grab_exc_value() + assert not excvalue def test_cond_call_gc_wb(self): def func_void(a, b): @@ -1524,108 +1526,92 @@ A = lltype.GcArray(lltype.Char) descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) - x = cpu.do_arraylen_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), - descr_A) - assert x.value == 5 + x = cpu.bh_arraylen_gc(descr_A, + lltype.cast_opaque_ptr(llmemory.GCREF, a)) + assert x == 5 # a[2] = 'Y' - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2), - descr_A) - assert x.value == ord('Y') + x = cpu.bh_getarrayitem_gc_i( + descr_A, lltype.cast_opaque_ptr(llmemory.GCREF, a), 2) + assert x == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3), - descr_B) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 3) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a if self.cpu.supports_floats: C = lltype.GcArray(lltype.Float) c = lltype.malloc(C, 6) c[3] = 3.5 descr_C = cpu.arraydescrof(C) - x = cpu.do_getarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(3), - descr_C) - assert isinstance(x, BoxFloat) - assert x.getfloat() == 3.5 - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, c)), BoxInt(4), - BoxFloat(4.5), descr_C) + x = cpu.bh_getarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 3) + assert x == 3.5 + cpu.bh_setarrayitem_gc_f( + descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 4, 4.5) assert c[4] == 4.5 s = rstr.mallocstr(6) - x = cpu.do_strlen( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))) - assert x.value == 6 + x = cpu.bh_strlen(lltype.cast_opaque_ptr(llmemory.GCREF, s)) + assert x == 6 # s.chars[3] = 'X' - x = cpu.do_strgetitem( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)) - assert x.value == ord('X') + x = cpu.bh_strgetitem(lltype.cast_opaque_ptr(llmemory.GCREF, s), 3) + assert x == ord('X') # S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A)), ('z', lltype.Float)) descrfld_x = cpu.fielddescrof(S, 'x') s = lltype.malloc(S) s.x = 'Z' - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_x) - assert x.value == ord('Z') - # - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(ord('4')), - descrfld_x) + x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x) + assert x == ord('Z') + # + cpu.bh_setfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_x, + ord('4')) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - descrfld_y) - assert isinstance(x, BoxPtr) - assert x.getref(lltype.Ptr(A)) == a + x = cpu.bh_getfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y) + assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a # s.y = lltype.nullptr(A) - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x, - descrfld_y) + cpu.bh_setfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_y, x) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char)) #, ('y', lltype.Ptr(A))) descrfld_rx = cpu.fielddescrof(RS, 'x') rs = lltype.malloc(RS, immortal=True) rs.x = '?' - x = cpu.do_getfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + x = cpu.bh_getfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), descrfld_rx) - assert x.value == ord('?') + assert x == ord('?') # - cpu.do_setfield_raw( - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(ord('!')), - descrfld_rx) + cpu.bh_setfield_raw_i( + heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)), + descrfld_rx, ord('!')) assert rs.x == '!' # if self.cpu.supports_floats: descrfld_z = cpu.fielddescrof(S, 'z') - cpu.do_setfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxFloat(3.5), - descrfld_z) + cpu.bh_setfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), + descrfld_z, 3.5) assert s.z == 3.5 s.z = 3.2 - x = cpu.do_getfield_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + x = cpu.bh_getfield_gc_f( + lltype.cast_opaque_ptr(llmemory.GCREF, s), descrfld_z) - assert x.getfloat() == 3.2 + assert x == 3.2 ### we don't support in the JIT for now GC pointers ### stored inside non-GC structs. #descrfld_ry = cpu.fielddescrof(RS, 'y') @@ -1643,45 +1629,43 @@ #assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new(descrsize) - assert isinstance(x, BoxPtr) - x.getref(lltype.Ptr(S)) + x = cpu.bh_new(descrsize) + lltype.cast_opaque_ptr(lltype.Ptr(S), x) # type check # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) - vtable2_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)) - cpu.set_class_sizes({vtable2_int: descrsize2}) - x = cpu.do_new_with_vtable(ConstInt(vtable2_int)) - assert isinstance(x, BoxPtr) + vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2)) + heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT) + x = cpu.bh_new_with_vtable(descrsize2, vtable2_int) + lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check # well... #assert x.getref(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array(BoxInt(7), arraydescr) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(A))) == 7 - # - cpu.do_setarrayitem_gc( - x, BoxInt(5), BoxInt(ord('*')), descr_A) - assert x.getref(lltype.Ptr(A))[5] == '*' - # - cpu.do_setarrayitem_gc( - BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), - BoxInt(1), x, - descr_B) - assert b[1] == x.getref(lltype.Ptr(A)) - # - x = cpu.do_newstr(BoxInt(5)) - assert isinstance(x, BoxPtr) - assert len(x.getref(lltype.Ptr(rstr.STR)).chars) == 5 - # - cpu.do_strsetitem(x, BoxInt(4), BoxInt(ord('/'))) - assert x.getref(lltype.Ptr(rstr.STR)).chars[4] == '/' - # - x = cpu.do_newstr(BoxInt(5)) - y = cpu.do_cast_ptr_to_int(x) - assert isinstance(y, BoxInt) - assert y.value == cpu.cast_gcref_to_int(x.value) + x = cpu.bh_new_array(arraydescr, 7) + array = lltype.cast_opaque_ptr(lltype.Ptr(A), x) + assert len(array) == 7 + # + cpu.bh_setarrayitem_gc_i(descr_A, x, 5, ord('*')) + assert array[5] == '*' + # + cpu.bh_setarrayitem_gc_r( + descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 1, x) + assert b[1] == array + # + x = cpu.bh_newstr(5) + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), x) + assert len(str.chars) == 5 + # + cpu.bh_strsetitem(x, 4, ord('/')) + assert str.chars[4] == '/' + # +## x = cpu.bh_newstr(5) +## y = cpu.bh_cast_ptr_to_int(x) +## z = cpu.bh_cast_ptr_to_int(x) +## y = rffi.get_real_int(y) +## z = rffi.get_real_int(z) +## assert type(y) == type(z) == int and y == z def test_sorting_of_fields(self): S = self.S @@ -1694,7 +1678,7 @@ def test_guards_nongc(self): x = lltype.malloc(lltype.Struct('x'), flavor='raw') - v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) vbox = BoxInt(v) ops = [ (rop.GUARD_NONNULL, vbox, False), @@ -1797,6 +1781,9 @@ malloc = staticmethod(ootype.new) nullptr = staticmethod(ootype.null) + def setup_class(cls): + py.test.skip("ootype tests skipped") + @classmethod def get_funcbox(cls, cpu, func_ptr): return BoxObj(ootype.cast_to_object(func_ptr)) Modified: pypy/branch/fast-forward/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/test/test_ll_random.py Sun Jun 20 18:38:42 2010 @@ -3,8 +3,9 @@ from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr -from pypy.jit.metainterp.history import ConstAddr, BoxPtr, BoxInt +from pypy.jit.metainterp.history import BoxPtr, BoxInt from pypy.jit.metainterp.history import BasicFailDescr +from pypy.jit.codewriter import heaptracker from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask from pypy.rpython.llinterp import LLException @@ -19,13 +20,11 @@ self.runicodes = [] self.structure_types = [] self.structure_types_and_vtables = [] - self.class_sizes_cache = [] def fork(self, cpu, loop, vars): fork = test_random.OperationBuilder.fork(self, cpu, loop, vars) fork.structure_types = self.structure_types fork.structure_types_and_vtables = self.structure_types_and_vtables - fork.class_sizes_cache = self.class_sizes_cache return fork def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): @@ -107,11 +106,7 @@ vtable.name[len(name)] = '\x00' self.structure_types_and_vtables.append((S, vtable)) # - vtable_adr = llmemory.cast_ptr_to_adr(vtable) - vtable_int = self.cpu.cast_adr_to_int(vtable_adr) - descr = self.cpu.sizeof(S) - self.class_sizes_cache.append((vtable_int, descr)) - self.cpu.set_class_sizes(dict(self.class_sizes_cache)) + heaptracker.register_known_gctype(self.cpu, vtable, S) # return S, vtable @@ -186,6 +181,9 @@ # ____________________________________________________________ +def ConstAddr(addr, cpu): + return ConstInt(heaptracker.adr2int(addr)) + class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): ptrvars = [(v, S) for (v, S) in builder.ptrvars @@ -507,8 +505,6 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(), descr=BasicFailDescr()) op.fail_args = fail_subset @@ -525,8 +521,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(), descr=BasicFailDescr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) @@ -546,8 +540,6 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) - assert builder.cpu.get_exception() - builder.cpu.clear_exception() while True: _, vtableptr = builder.get_random_structure_type_and_vtable(r) if vtableptr != exc: Modified: pypy/branch/fast-forward/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/test/test_random.py Sun Jun 20 18:38:42 2010 @@ -4,7 +4,7 @@ from pypy.jit.backend.test import conftest as demo_conftest from pypy.jit.metainterp.history import BasicFailDescr, TreeLoop from pypy.jit.metainterp.history import BoxInt, ConstInt, LoopToken -from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat, Const from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute_nonspec @@ -17,9 +17,14 @@ def __init__(self, subops): self.operations = subops +class FakeMetaInterp(object): + def execute_raised(self, exc, constant=False): + self._got_exc = exc + class OperationBuilder(object): def __init__(self, cpu, loop, vars): self.cpu = cpu + self.fakemetainterp = FakeMetaInterp() self.loop = loop self.intvars = [box for box in vars if isinstance(box, BoxInt)] self.boolvars = [] # subset of self.intvars @@ -40,7 +45,9 @@ return fork def do(self, opnum, argboxes, descr=None): - v_result = execute_nonspec(self.cpu, opnum, argboxes, descr) + self.fakemetainterp._got_exc = None + v_result = execute_nonspec(self.cpu, self.fakemetainterp, + opnum, argboxes, descr) if isinstance(v_result, Const): v_result = v_result.clonebox() self.loop.operations.append(ResOperation(opnum, argboxes, v_result, @@ -56,11 +63,14 @@ if S == S2 and not (isinstance(v, ConstPtr) and isinstance(v2, ConstPtr)): if r.random() < 0.5: - return self.do(rop.OOIS, [v, v2]) + return self.do(rop.PTR_EQ, [v, v2]) else: - return self.do(rop.OOISNOT, [v, v2]) + return self.do(rop.PTR_NE, [v, v2]) v = r.choice(self.intvars) - return self.do(rop.INT_IS_TRUE, [v]) + if r.random() < 0.7: + return self.do(rop.INT_IS_TRUE, [v]) + else: + return self.do(rop.INT_IS_ZERO, [v]) def subset_of_intvars(self, r): subset = [] @@ -79,16 +89,16 @@ for v in op.args: if v in names: args.append(names[v]) - elif isinstance(v, ConstAddr): - try: - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - except AttributeError: - args.append('ConstAddr(...)') - else: - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) +## elif isinstance(v, ConstAddr): +## try: +## name = ''.join([v.value.ptr.name[i] +## for i in range(len(v.value.ptr.name)-1)]) +## except AttributeError: +## args.append('ConstAddr(...)') +## else: +## args.append( +## 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' +## % name) elif isinstance(v, ConstFloat): args.append('ConstFloat(%r)' % v.value) elif isinstance(v, ConstInt): @@ -264,8 +274,8 @@ fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) - if builder.cpu._overflow_flag: # overflow detected - del builder.cpu._overflow_flag + if builder.fakemetainterp._got_exc: # overflow detected + assert isinstance(builder.fakemetainterp._got_exc, OverflowError) op = ResOperation(rop.GUARD_OVERFLOW, [], None) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including @@ -413,7 +423,7 @@ OPERATIONS.append(UnaryOperation(_op)) OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) -OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True)) +OPERATIONS.append(UnaryOperation(rop.INT_IS_ZERO, boolres=True)) OPERATIONS.append(ConstUnaryOperation(rop.SAME_AS, boolres='sometimes')) for _op in [rop.INT_ADD_OVF, @@ -434,8 +444,6 @@ ]: OPERATIONS.append(UnaryFloatOperation(_op)) -OPERATIONS.append(UnaryFloatOperation(rop.FLOAT_IS_TRUE, boolres=True)) - OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT)) OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT)) @@ -587,8 +595,8 @@ def run_loop(self): cpu = self.builder.cpu self.clear_state() - assert not cpu.get_exception() - assert not cpu.get_exc_value() + exc = cpu.grab_exc_value() + assert not exc for i, box in enumerate(self.startvars): if isinstance(box, BoxInt): @@ -609,15 +617,13 @@ self.expected[v], i) ) + exc = cpu.grab_exc_value() if (self.guard_op is not None and self.guard_op.is_guard_exception()): if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: - assert cpu.get_exception() - assert cpu.get_exc_value() - cpu.clear_exception() + assert exc else: - assert not cpu.get_exception() - assert not cpu.get_exc_value() + assert not exc def build_bridge(self): def exc_handling(guard_op): Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py Sun Jun 20 18:38:42 2010 @@ -633,8 +633,8 @@ genop_int_ne = _cmpop("NE", "NE") genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") - genop_oois = genop_int_eq - genop_ooisnot = genop_int_ne + genop_ptr_eq = genop_int_eq + genop_ptr_ne = genop_int_ne genop_float_lt = _cmpop_float('B') genop_float_le = _cmpop_float('BE') @@ -654,8 +654,8 @@ genop_guard_int_ne = _cmpop_guard("NE", "NE", "E", "E") genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") - genop_guard_oois = genop_guard_int_eq - genop_guard_ooisnot = genop_guard_int_ne + genop_guard_ptr_eq = genop_guard_int_eq + genop_guard_ptr_ne = genop_guard_int_ne genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") @@ -689,32 +689,6 @@ # Following what gcc does: res = x & 0x7FFFFFFFFFFFFFFF self.mc.ANDPD(arglocs[0], self.loc_float_const_abs) - def genop_guard_float_is_true(self, op, guard_op, addr, arglocs, resloc): - guard_opnum = guard_op.opnum - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - mc = self.mc._mc - if guard_opnum == rop.GUARD_TRUE: - mc.JP(rel8(6)) - mc.JZ(rel32(addr)) - return mc.tell() - 4 - else: - mc.JP(rel8(2)) - mc.JZ(rel8(5)) - return self.implement_guard(addr, mc.JMP) - - def genop_float_is_true(self, op, arglocs, resloc): - loc0, loc1 = arglocs - self.mc.XORPD(loc0, loc0) - self.mc.UCOMISD(loc0, loc1) - rl = resloc.lowest8bits() - rh = resloc.higher8bits() - self.mc.SETNE(rl) - self.mc.SETP(rh) - self.mc.OR(rl, rh) - self.mc.MOVZX(resloc, rl) - def genop_cast_float_to_int(self, op, arglocs, resloc): self.mc.CVTTSD2SI(resloc, arglocs[0]) @@ -753,7 +727,7 @@ self.mc.SETNE(rl) self.mc.MOVZX(resloc, rl) - def genop_guard_bool_not(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_zero(self, op, guard_op, addr, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm8(0)) if guard_opnum == rop.GUARD_TRUE: @@ -761,13 +735,15 @@ else: return self.implement_guard(addr, self.mc.JZ) - def genop_bool_not(self, op, arglocs, resloc): - self.mc.XOR(arglocs[0], imm8(1)) + def genop_int_is_zero(self, op, arglocs, resloc): + self.mc.CMP(arglocs[0], imm8(0)) + rl = resloc.lowest8bits() + self.mc.SETE(rl) + self.mc.MOVZX(resloc, rl) def genop_same_as(self, op, arglocs, resloc): self.mov(arglocs[0], resloc) - genop_cast_ptr_to_int = genop_same_as - genop_virtual_ref = genop_same_as + #genop_cast_ptr_to_int = genop_same_as def genop_int_mod(self, op, arglocs, resloc): self.mc.CDQ() @@ -1115,13 +1091,8 @@ n = self.CODE_HOLE mc.writechr(n) mc.writechr(self.CODE_STOP) - # preallocate the fail_boxes - i = len(failargs) - 1 - if i >= 0: - self.fail_boxes_int.get_addr_for_num(i) - self.fail_boxes_ptr.get_addr_for_num(i) - if self.cpu.supports_floats: - self.fail_boxes_float.get_addr_for_num(i) + # assert that the fail_boxes lists are big enough + assert len(failargs) <= self.fail_boxes_int.SIZE def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager @@ -1165,39 +1136,6 @@ arglocs.append(loc) return arglocs[:] - def make_boxes_from_latest_values(self, bytecode): - bytecode = rffi.cast(rffi.UCHARP, bytecode) - boxes = [] - while 1: - # decode the next instruction from the bytecode - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - kind = code & 3 - while code > 0x7F: - code = rffi.cast(lltype.Signed, bytecode[0]) - bytecode = rffi.ptradd(bytecode, 1) - index = len(boxes) - if kind == self.DESCR_INT: - box = BoxInt(self.fail_boxes_int.getitem(index)) - elif kind == self.DESCR_REF: - box = BoxPtr(self.fail_boxes_ptr.getitem(index)) - # clear after reading (xxx duplicates - # get_latest_value_ref()) - self.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - elif kind == self.DESCR_FLOAT: - box = BoxFloat(self.fail_boxes_float.getitem(index)) - else: - assert kind == self.DESCR_SPECIAL - if code == self.CODE_STOP: - break - elif code == self.CODE_HOLE: - box = None - else: - assert 0, "bad code" - boxes.append(box) - return boxes - @rgc.no_collect def grab_frame_values(self, bytecode, frame_addr, allregisters): # no malloc allowed here!! @@ -1258,6 +1196,7 @@ # if not we_are_translated(): assert bytecode[4] == 0xCC + self.fail_boxes_count = num fail_index = rffi.cast(rffi.LONGP, bytecode)[0] return fail_index @@ -1407,8 +1346,6 @@ self.mc.AND(eax, imm(0xff)) elif size == 2: self.mc.AND(eax, imm(0xffff)) - - genop_call_pure = genop_call def genop_guard_call_may_force(self, op, guard_op, addr, arglocs, result_loc): @@ -1427,28 +1364,79 @@ descr = op.descr assert isinstance(descr, LoopToken) assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) + # + # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() - mc.CMP(eax, imm(self.cpu.done_with_this_frame_int_v)) - mc.JE(rel8_patched_later) + if op.result is None: + assert result_loc is None + value = self.cpu.done_with_this_frame_void_v + else: + kind = op.result.type + if kind == INT: + assert result_loc is eax + value = self.cpu.done_with_this_frame_int_v + elif kind == REF: + assert result_loc is eax + value = self.cpu.done_with_this_frame_ref_v + elif kind == FLOAT: + value = self.cpu.done_with_this_frame_float_v + else: + raise AssertionError(kind) + mc.CMP(eax, imm(value)) + mc.JE(rel8_patched_later) # goto B if we get 'done_with_this_frame' je_location = mc.get_relative_pos() + # + # Path A: use assembler_helper_adr self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) - mc.JMP(rel8_patched_later) + if isinstance(result_loc, MODRM64): + mc.FSTP(result_loc) + #else: result_loc is already either eax or None, checked below + mc.JMP(rel8_patched_later) # done jmp_location = mc.get_relative_pos() + # + # Path B: fast path. Must load the return value, and reset the token offset = jmp_location - je_location assert 0 < offset <= 127 mc.overwrite(je_location - 1, [chr(offset)]) - mc.MOV(eax, heap(self.fail_boxes_int.get_addr_for_num(0))) + # + # Reset the vable token --- XXX really too much special logic here:-( + if self.cpu.index_of_virtualizable >= 0: + from pypy.jit.backend.llsupport.descr import BaseFieldDescr + fielddescr = self.cpu.vable_token_descr + assert isinstance(fielddescr, BaseFieldDescr) + ofs = fielddescr.offset + mc.MOV(eax, arglocs[1]) + mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + # in the line above, TOKEN_NONE = 0 + # + if op.result is not None: + # load the return value from fail_boxes_xxx[0] + kind = op.result.type + if kind == FLOAT: + xmmtmp = X86XMMRegisterManager.all_regs[0] + adr = self.fail_boxes_float.get_addr_for_num(0) + mc.MOVSD(xmmtmp, heap64(adr)) + mc.MOVSD(result_loc, xmmtmp) + else: + assert result_loc is eax + if kind == INT: + adr = self.fail_boxes_int.get_addr_for_num(0) + mc.MOV(eax, heap(adr)) + elif kind == REF: + adr = self.fail_boxes_ptr.get_addr_for_num(0) + mc.XOR(eax, eax) + mc.XCHG(eax, heap(adr)) + else: + raise AssertionError(kind) + # + # Here we join Path A and Path B again offset = mc.get_relative_pos() - jmp_location - assert 0 < offset <= 127 + assert 0 <= offset <= 127 mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() - if isinstance(result_loc, MODRM64): - self.mc.FSTP(result_loc) - else: - assert result_loc is eax or result_loc is None self.mc.CMP(mem(ebp, FORCE_INDEX_OFS), imm(0)) return self.implement_guard(addr, self.mc.JL) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,7 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, ConstAddr, BoxPtr, + ResOperation, BoxPtr, LoopToken, INT, REF, FLOAT) from pypy.jit.backend.x86.ri386 import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr @@ -11,6 +11,7 @@ from pypy.rlib import rgc from pypy.jit.backend.llsupport import symbolic from pypy.jit.backend.x86.jump import remap_frame_layout +from pypy.jit.codewriter import heaptracker from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr @@ -45,8 +46,6 @@ print "convert_to_imm: ConstPtr needs special care" raise AssertionError return imm(rffi.cast(lltype.Signed, c.value)) - elif isinstance(c, ConstAddr): - return imm(ll2ctypes.cast_adr_to_int(c.value)) else: print "convert_to_imm: got a %s" % c raise AssertionError @@ -550,8 +549,8 @@ consider_uint_lt = _consider_compop consider_uint_le = _consider_compop consider_uint_ge = _consider_compop - consider_oois = _consider_compop - consider_ooisnot = _consider_compop + consider_ptr_eq = _consider_compop + consider_ptr_ne = _consider_compop def _consider_float_op(self, op): loc1 = self.xrm.loc(op.args[1]) @@ -593,20 +592,6 @@ self.Perform(op, [loc0], loc0) self.xrm.possibly_free_var(op.args[0]) - def consider_float_is_true(self, op, guard_op): - # doesn't need arg to be in a register - tmpbox0 = TempBox() - loc0 = self.xrm.force_allocate_reg(tmpbox0) - loc1 = self.xrm.loc(op.args[0]) - arglocs = [loc0, loc1] - self.xrm.possibly_free_var(op.args[0]) - self.xrm.possibly_free_var(tmpbox0) - if guard_op is not None: - self.perform_with_guard(op, guard_op, arglocs, None) - else: - loc2 = self.rm.force_allocate_reg(op.result, need_lower_byte=True) - self.Perform(op, arglocs, loc2) - def consider_cast_float_to_int(self, op): loc0 = self.xrm.make_sure_var_in_reg(op.args[0], imm_fine=False) loc1 = self.rm.force_allocate_reg(op.result) @@ -645,7 +630,6 @@ def consider_call(self, op): self._consider_call(op) - consider_call_pure = consider_call def consider_call_may_force(self, op, guard_op): assert guard_op is not None @@ -656,7 +640,7 @@ portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) vable_index = self.assembler.cpu.index_of_virtualizable - if vable_index != -1: + if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) else: @@ -725,7 +709,7 @@ def consider_new_with_vtable(self, op): classint = op.args[0].getint() - descrsize = self.assembler.cpu.class_sizes[classint] + descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint) if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize): self._fastpath_malloc(op, descrsize) self.assembler.set_vtable(eax, imm(classint)) @@ -889,22 +873,14 @@ resloc = self.rm.force_allocate_reg(op.result, need_lower_byte=True) self.Perform(op, [argloc], resloc) - def consider_bool_not(self, op, guard_op): - if guard_op is not None: - # doesn't need arg to be in a register - argloc = self.loc(op.args[0]) - self.rm.possibly_free_var(op.args[0]) - self.perform_with_guard(op, guard_op, [argloc], None) - else: - self.consider_int_neg(op) + consider_int_is_zero = consider_int_is_true def consider_same_as(self, op): argloc = self.loc(op.args[0]) self.possibly_free_var(op.args[0]) resloc = self.force_allocate_reg(op.result) self.Perform(op, [argloc], resloc) - consider_cast_ptr_to_int = consider_same_as - consider_virtual_ref = consider_same_as + #consider_cast_ptr_to_int = consider_same_as def consider_strlen(self, op): base_loc = self.rm.make_sure_var_in_reg(op.args[0], op.args) @@ -963,9 +939,6 @@ def consider_debug_merge_point(self, op): pass - def consider_virtual_ref_finish(self, op): - self.possibly_free_vars(op.args) - def get_mark_gc_roots(self, gcrootmap): shape = gcrootmap.get_basic_shape() for v, val in self.fm.frame_bindings.items(): @@ -973,6 +946,8 @@ assert isinstance(val, MODRM) gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position)) for v, reg in self.rm.reg_bindings.items(): + if reg is eax: + continue # ok to ignore this one if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)): if reg is ebx: gcrootmap.add_ebx(shape) @@ -981,7 +956,8 @@ elif reg is edi: gcrootmap.add_edi(shape) else: - assert reg is eax # ok to ignore this one + print "[get_mark_gc_roots] bogus register", reg + assert False return gcrootmap.compress_callshape(shape) def consider_force_token(self, op): Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/ri386.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/ri386.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/ri386.py Sun Jun 20 18:38:42 2010 @@ -210,7 +210,7 @@ class REL32(OPERAND): width = 4 def __init__(self, absolute_target): - self.absolute_target = absolute_target + self.absolute_target = get_real_int(absolute_target) def assembler(self): return '%d' % (self.absolute_target,) @@ -286,11 +286,14 @@ rel32 = REL32 rel8 = REL8 +def get_real_int(x): + from pypy.rpython.lltypesystem import rffi, lltype + return rffi.cast(lltype.Signed, x) # force as a real int + def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() - if not we_are_translated(): - assert type(value) is int + value = get_real_int(value) if single_byte(value): return imm8(value) else: Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py Sun Jun 20 18:38:42 2010 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp import history, compile @@ -67,19 +68,20 @@ return self.assembler.fail_boxes_float.getitem(index) def get_latest_value_ref(self, index): - ptrvalue = self.assembler.fail_boxes_ptr.getitem(index) - # clear after reading - self.assembler.fail_boxes_ptr.setitem(index, lltype.nullptr( - llmemory.GCREF.TO)) - return ptrvalue + return self.assembler.fail_boxes_ptr.getitem(index) + + def get_latest_value_count(self): + return self.assembler.fail_boxes_count + + def clear_latest_values(self, count): + setitem = self.assembler.fail_boxes_ptr.setitem + null = lltype.nullptr(llmemory.GCREF.TO) + for index in range(count): + setitem(index, null) def get_latest_force_token(self): return self.assembler.fail_ebp + FORCE_INDEX_OFS - def make_boxes_from_latest_values(self, faildescr): - return self.assembler.make_boxes_from_latest_values( - faildescr._x86_failure_recovery_bytecode) - def execute_token(self, executable_token): addr = executable_token._x86_bootstrap_code func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr) @@ -136,9 +138,6 @@ CPU = CPU386 -import pypy.jit.metainterp.executor -pypy.jit.metainterp.executor.make_execute_list(CPU) - # silence warnings history.LoopToken._x86_param_depth = 0 Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/support.py Sun Jun 20 18:38:42 2010 @@ -4,6 +4,8 @@ ATP = lltype.GcArray(TP) class ValuesArray(object): + SIZE = size + def __init__(self): self.ar = lltype.malloc(ATP, size, zero=True, immortal=True) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py Sun Jun 20 18:38:42 2010 @@ -75,35 +75,6 @@ assert ([loc.assembler() for loc in newlocs] == [loc.assembler() for loc in locs if loc is not None]) - # finally, test make_boxes_from_latest_values(), which should - # reproduce the holes - expected_classes = [BoxInt, BoxPtr, BoxFloat, - BoxInt, BoxPtr, BoxFloat, - type(None), type(None), - BoxInt, BoxPtr, BoxFloat] - ptrvalues = {} - S = lltype.GcStruct('S') - for i, cls in enumerate(expected_classes): - if cls == BoxInt: - assembler.fail_boxes_int.setitem(i, 1000 + i) - elif cls == BoxPtr: - s = lltype.malloc(S) - s_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s) - ptrvalues[i] = s_ref - assembler.fail_boxes_ptr.setitem(i, s_ref) - elif cls == BoxFloat: - assembler.fail_boxes_float.setitem(i, 42.5 + i) - boxes = assembler.make_boxes_from_latest_values(bytecode_addr) - assert len(boxes) == len(locs) == len(expected_classes) - for i, (box, expected_class) in enumerate(zip(boxes, expected_classes)): - assert type(box) is expected_class - if expected_class == BoxInt: - assert box.value == 1000 + i - elif expected_class == BoxPtr: - assert box.value == ptrvalues[i] - elif expected_class == BoxFloat: - assert box.value == 42.5 + i - # ____________________________________________________________ def test_failure_recovery_func_no_floats(): @@ -244,6 +215,13 @@ # bits of the float were correctly saved and restored. assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + # verify that until clear_latest_values() is called, reading the + # same values multiple times work + for i in range(len(content)): + assert assembler.fail_boxes_int.getitem(i) == expected_ints[i] + assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i] + assert assembler.fail_boxes_float.getitem(i) == expected_floats[i] + class FakeProfileAgent(object): def __init__(self): self.functions = [] Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_basic.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,7 @@ from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.test import test_basic -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE class Jit386Mixin(test_basic.LLJitMixin): Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py Sun Jun 20 18:38:42 2010 @@ -3,9 +3,10 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llsupport.descr import GcCache from pypy.jit.backend.llsupport.gc import GcLLDescription from pypy.jit.backend.x86.runner import CPU @@ -21,7 +22,6 @@ from pypy.jit.backend.x86.test.test_regalloc import BaseTestRegalloc from pypy.jit.backend.x86.regalloc import X86RegisterManager, X86FrameManager,\ X86XMMRegisterManager -from pypy.rpython.annlowlevel import llhelper class MockGcRootMap(object): def get_basic_shape(self): @@ -225,10 +225,12 @@ self.nodedescr = nodedescr vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) vtable_int = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable)) - NODE2 = lltype.Struct('node2', ('tid', lltype.Signed), + NODE2 = lltype.GcStruct('node2', + ('parent', rclass.OBJECT), + ('tid', lltype.Signed), ('vtable', lltype.Ptr(rclass.OBJECT_VTABLE))) descrsize = cpu.sizeof(NODE2) - cpu.set_class_sizes({vtable_int: descrsize}) + heaptracker.register_known_gctype(cpu, vtable, NODE2) self.descrsize = descrsize self.vtable_int = vtable_int @@ -282,4 +284,4 @@ assert gc_ll_descr.nursery[0] == self.descrsize.tid assert gc_ll_descr.nursery[1] == self.vtable_int nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - assert gc_ll_descr.addrs[0] == nurs_adr + 8 + assert gc_ll_descr.addrs[0] == nurs_adr + 12 Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,7 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ +from pypy.jit.metainterp.history import BoxInt, ConstInt,\ BoxPtr, ConstPtr, LoopToken, BasicFailDescr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.backend.llsupport.descr import GcCache @@ -211,10 +211,9 @@ ''' S = lltype.GcStruct('S') ptr = lltype.malloc(S) + self.cpu.clear_latest_values(2) self.interpret(ops, [0, ptr]) assert self.getptr(0, lltype.Ptr(S)) == ptr - assert not self.cpu.assembler.fail_boxes_ptr.getitem(0) - assert not self.cpu.assembler.fail_boxes_ptr.getitem(1) def test_exception_bridge_no_exception(self): ops = ''' @@ -522,18 +521,20 @@ assert self.getint(0) == 0 def test_bug_float_is_true_stack(self): + # NB. float_is_true no longer exists. Unsure if keeping this test + # makes sense any more. ops = ''' [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9] - i0 = float_is_true(f0) - i1 = float_is_true(f1) - i2 = float_is_true(f2) - i3 = float_is_true(f3) - i4 = float_is_true(f4) - i5 = float_is_true(f5) - i6 = float_is_true(f6) - i7 = float_is_true(f7) - i8 = float_is_true(f8) - i9 = float_is_true(f9) + i0 = float_ne(f0, 0.0) + i1 = float_ne(f1, 0.0) + i2 = float_ne(f2, 0.0) + i3 = float_ne(f3, 0.0) + i4 = float_ne(f4, 0.0) + i5 = float_ne(f5, 0.0) + i6 = float_ne(f6, 0.0) + i7 = float_ne(f7, 0.0) + i8 = float_ne(f8, 0.0) + i9 = float_ne(f9, 0.0) finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) ''' loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9]) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py Sun Jun 20 18:38:42 2010 @@ -35,7 +35,7 @@ ResOperation(rop.INT_MUL, [v1, v1], v2), ResOperation(rop.INT_MUL, [v2, v1], v3), ResOperation(rop.INT_IS_TRUE, [v2], tmp5), - ResOperation(rop.BOOL_NOT, [tmp5], v4), + ResOperation(rop.INT_IS_ZERO, [tmp5], v4), ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()), ] cpu = CPU(None, None) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py Sun Jun 20 18:38:42 2010 @@ -259,9 +259,11 @@ self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) if guard == rop.GUARD_FALSE: - assert result == execute(self.cpu, op, None, b).value + assert result == execute(self.cpu, None, + op, None, b).value else: - assert result != execute(self.cpu, op, None, b).value + assert result != execute(self.cpu, None, + op, None, b).value def test_stuff_followed_by_guard(self): @@ -304,7 +306,7 @@ self.cpu.set_future_value_int(i, box.value) self.cpu.execute_token(looptoken) result = self.cpu.get_latest_value_int(0) - expected = execute(self.cpu, op, None, a, b).value + expected = execute(self.cpu, None, op, None, a, b).value if guard == rop.GUARD_FALSE: assert result == expected else: Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_send.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_send.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_send.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,6 @@ import py from pypy.jit.metainterp.test.test_send import SendTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rlib import jit class TestSend(Jit386Mixin, SendTests): Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zrpy_gc.py Sun Jun 20 18:38:42 2010 @@ -94,7 +94,7 @@ def run(cbuilder, args=''): # pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': str(pypylog)}) + data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) return data.strip() def compile_and_run(f, gc, **kwds): @@ -174,7 +174,7 @@ def run(self, name, n=2000): pypylog = udir.join('TestCompileHybrid.log') res = self.cbuilder.cmdexec("%s %d" %(name, n), - env={'PYPYLOG': str(pypylog)}) + env={'PYPYLOG': ':%s' % pypylog}) assert int(res) == 20 def run_orig(self, name, n, x): Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py Sun Jun 20 18:38:42 2010 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.jitprof import Profiler from pypy.jit.backend.x86.runner import CPU386 from pypy.jit.backend.test.support import CCompiledMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.translator.translator import TranslationContext class TestTranslationX86(CCompiledMixin): @@ -38,7 +38,7 @@ return abs(x) jitdriver = JitDriver(greens = [], - reds = ['frame', 'total', 'j'], + reds = ['total', 'frame', 'j'], virtualizables = ['frame']) def f(i, j): for param in unroll_parameters: @@ -72,7 +72,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -127,8 +127,14 @@ def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) + class ImDone(Exception): + def __init__(self, resvalue): + self.resvalue = resvalue + @dont_look_inside - def f(x): + def f(x, total): + if x <= 3: + raise ImDone(total * 10) if x > 20: return 2 raise ValueError @@ -149,16 +155,16 @@ return Sub() else: return Base() - def main(i): + def myportal(i): jitdriver.set_param("threshold", 3) jitdriver.set_param("trace_eagerness", 2) total = 0 n = i - while n > 3: + while True: jitdriver.can_enter_jit(n=n, total=total) jitdriver.jit_merge_point(n=n, total=total) try: - total += f(n) + total += f(n, total) except ValueError: total += 1 try: @@ -166,7 +172,11 @@ except ValueError: total -= 1 n -= h(n).meth() # this is to force a GUARD_CLASS - return total * 10 + def main(i): + try: + myportal(i) + except ImDone, e: + return e.resvalue # XXX custom fishing, depends on the exact env var and format logfile = udir.join('test_ztranslation.log') Modified: pypy/branch/fast-forward/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/compile.py Sun Jun 20 18:38:42 2010 @@ -4,6 +4,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import debug_start, debug_stop from pypy.conftest import option +from pypy.tool.sourcetools import func_with_new_name from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import TreeLoop, Box, History, LoopToken @@ -14,8 +15,10 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.jit.metainterp.optimizeutil import InvalidLoop -class GiveUp(Exception): - pass +def giveup(): + from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole + from pypy.jit.metainterp.jitprof import ABORT_BRIDGE + raise SwitchToBlackhole(ABORT_BRIDGE) def show_loop(metainterp_sd, loop=None, error=None): # debugging @@ -153,6 +156,7 @@ assert metainterp_sd.result_type == 'ref' cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): @@ -165,6 +169,7 @@ def handle_fail(self, metainterp_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) + cpu.clear_latest_values(1) raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value) @@ -220,6 +225,11 @@ rd_virtuals = None rd_pendingfields = None + CNT_INT = -0x20000000 + CNT_REF = -0x40000000 + CNT_FLOAT = -0x60000000 + CNT_MASK = 0x1FFFFFFF + def __init__(self, metainterp_sd, original_greenkey): ResumeDescr.__init__(self, original_greenkey) self.metainterp_sd = metainterp_sd @@ -236,23 +246,64 @@ except ValueError: return # xxx probably very rare else: - self._counter = ~i # use ~(index_of_guarded_box_in_fail_args) + if box.type == history.INT: + cnt = self.CNT_INT + elif box.type == history.REF: + cnt = self.CNT_REF + elif box.type == history.FLOAT: + cnt = self.CNT_FLOAT + else: + assert 0, box.type + # we build the following value for _counter, which is always + # a negative value + self._counter = cnt | i def handle_fail(self, metainterp_sd): + if self.must_compile(metainterp_sd): + return self._trace_and_compile_from_bridge(metainterp_sd) + else: + from pypy.jit.metainterp.blackhole import resume_in_blackhole + resume_in_blackhole(metainterp_sd, self) + assert 0, "unreachable" + + def _trace_and_compile_from_bridge(self, metainterp_sd): from pypy.jit.metainterp.pyjitpl import MetaInterp metainterp = MetaInterp(metainterp_sd) return metainterp.handle_guard_failure(self) + _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd, inputargs_and_holes): + def must_compile(self, metainterp_sd): trace_eagerness = metainterp_sd.state.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness else: - box = inputargs_and_holes[~self._counter] - if self._counters is None: - self._counters = ResumeGuardCounters() - counter = self._counters.see(box) + index = self._counter & self.CNT_MASK + typetag = self._counter & ~ self.CNT_MASK + counters = self._counters + if typetag == self.CNT_INT: + intvalue = metainterp_sd.cpu.get_latest_value_int(index) + if counters is None: + self._counters = counters = ResumeGuardCountersInt() + else: + assert isinstance(counters, ResumeGuardCountersInt) + counter = counters.see_int(intvalue) + elif typetag == self.CNT_REF: + refvalue = metainterp_sd.cpu.get_latest_value_ref(index) + if counters is None: + self._counters = counters = ResumeGuardCountersRef() + else: + assert isinstance(counters, ResumeGuardCountersRef) + counter = counters.see_ref(refvalue) + elif typetag == self.CNT_FLOAT: + floatvalue = metainterp_sd.cpu.get_latest_value_float(index) + if counters is None: + self._counters = counters = ResumeGuardCountersFloat() + else: + assert isinstance(counters, ResumeGuardCountersFloat) + counter = counters.see_float(floatvalue) + else: + assert 0, typetag return counter >= trace_eagerness def reset_counter_from_failure(self): @@ -283,17 +334,17 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): def handle_fail(self, metainterp_sd): - from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + # Failures of a GUARD_NOT_FORCED are never compiled, but + # always just blackholed. First fish for the data saved when + # the virtualrefs and virtualizable have been forced by + # handle_async_forcing() just a moment ago. + from pypy.jit.metainterp.blackhole import resume_in_blackhole token = metainterp_sd.cpu.get_latest_force_token() all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - metainterp._already_allocated_resume_virtuals = all_virtuals - return metainterp.handle_guard_failure(self) - - def must_compile(self, metainterp_sd, inputargs_and_holes): - return False # never compile GUARD_NOT_FORCED failures + resume_in_blackhole(metainterp_sd, self, all_virtuals) + assert 0, "unreachable" @staticmethod def force_now(cpu, token): @@ -305,91 +356,101 @@ faildescr.handle_async_forcing(token) def handle_async_forcing(self, force_token): - from pypy.jit.metainterp.pyjitpl import MetaInterp from pypy.jit.metainterp.resume import force_from_resumedata - # To handle the forcing itself, we create a temporary MetaInterp - # as a convenience to move the various data to its proper place. metainterp_sd = self.metainterp_sd - metainterp = MetaInterp(metainterp_sd) - metainterp.history = None # blackholing - liveboxes = metainterp_sd.cpu.make_boxes_from_latest_values(self) - # - expect_virtualizable = metainterp_sd.virtualizable_info is not None - forced_data = force_from_resumedata(metainterp, liveboxes, self, - expect_virtualizable) - virtualizable_boxes, virtualref_boxes, all_virtuals = forced_data - # - # Handle virtualref_boxes: mark each JIT_VIRTUAL_REF as forced - vrefinfo = metainterp_sd.virtualref_info - for i in range(0, len(virtualref_boxes), 2): - virtualbox = virtualref_boxes[i] - vrefbox = virtualref_boxes[i+1] - vrefinfo.forced_single_vref(vrefbox.getref_base(), - virtualbox.getref_base()) - # Handle virtualizable_boxes: store them on the real virtualizable now - if expect_virtualizable: - metainterp_sd.virtualizable_info.forced_vable(virtualizable_boxes) + all_virtuals = force_from_resumedata(metainterp_sd, self) + # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED self.save_data(force_token, all_virtuals) def save_data(self, key, value): globaldata = self.metainterp_sd.globaldata - assert key not in globaldata.resume_virtuals - globaldata.resume_virtuals[key] = value + if we_are_translated(): + assert key not in globaldata.resume_virtuals + globaldata.resume_virtuals[key] = value + else: + rv = globaldata.resume_virtuals_not_translated + for key1, value1 in rv: + assert key1 != key + rv.append((key, value)) def fetch_data(self, key): globaldata = self.metainterp_sd.globaldata - assert key in globaldata.resume_virtuals - data = globaldata.resume_virtuals[key] - del globaldata.resume_virtuals[key] + if we_are_translated(): + assert key in globaldata.resume_virtuals + data = globaldata.resume_virtuals[key] + del globaldata.resume_virtuals[key] + else: + rv = globaldata.resume_virtuals_not_translated + for i in range(len(rv)): + if rv[i][0] == key: + data = rv[i][1] + del rv[i] + break + else: + assert 0, "not found: %r" % (key,) return data -class ResumeGuardCounters(object): - # Completely custom algorithm for now: keep 5 pairs (box, counter), +class AbstractResumeGuardCounters(object): + # Completely custom algorithm for now: keep 5 pairs (value, counter), # and when we need more, we discard the middle pair (middle in the # current value of the counter). That way, we tend to keep the - # boxes with a high counter, but also we avoid always throwing away - # the most recently added box. **THIS ALGO MUST GO AWAY AT SOME POINT** + # values with a high counter, but also we avoid always throwing away + # the most recently added value. **THIS ALGO MUST GO AWAY AT SOME POINT** + pass +def _see(self, newvalue): + # find and update an existing counter + unused = -1 + for i in range(5): + cnt = self.counters[i] + if cnt: + if self.values[i] == newvalue: + cnt += 1 + self.counters[i] = cnt + return cnt + else: + unused = i + # not found. Use a previously unused entry, if there is one + if unused >= 0: + self.counters[unused] = 1 + self.values[unused] = newvalue + return 1 + # no unused entry. Overwrite the middle one. Computed with indices + # a, b, c meaning the highest, second highest, and third highest + # entries. + a = 0 + b = c = -1 + for i in range(1, 5): + if self.counters[i] > self.counters[a]: + c = b; b = a; a = i + elif b < 0 or self.counters[i] > self.counters[b]: + c = b; b = i + elif c < 0 or self.counters[i] > self.counters[c]: + c = i + self.counters[c] = 1 + self.values[c] = newvalue + return 1 + +class ResumeGuardCountersInt(AbstractResumeGuardCounters): def __init__(self): self.counters = [0] * 5 - self.boxes = [None] * 5 + self.values = [0] * 5 + see_int = func_with_new_name(_see, 'see_int') - def see(self, newbox): - newbox = newbox.constbox() - # find and update an existing counter - unused = -1 - for i in range(5): - cnt = self.counters[i] - if cnt: - if newbox.same_constant(self.boxes[i]): - cnt += 1 - self.counters[i] = cnt - return cnt - else: - unused = i - # not found. Use a previously unused entry, if there is one - if unused >= 0: - self.counters[unused] = 1 - self.boxes[unused] = newbox - return 1 - # no unused entry. Overwrite the middle one. Computed with indices - # a, b, c meaning the highest, second highest, and third highest - # entries. - a = 0 - b = c = -1 - for i in range(1, 5): - if self.counters[i] > self.counters[a]: - c = b; b = a; a = i - elif b < 0 or self.counters[i] > self.counters[b]: - c = b; b = i - elif c < 0 or self.counters[i] > self.counters[c]: - c = i - self.counters[c] = 1 - self.boxes[c] = newbox - return 1 +class ResumeGuardCountersRef(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [history.ConstPtr.value] * 5 + see_ref = func_with_new_name(_see, 'see_ref') + +class ResumeGuardCountersFloat(AbstractResumeGuardCounters): + def __init__(self): + self.counters = [0] * 5 + self.values = [0.0] * 5 + see_float = func_with_new_name(_see, 'see_float') class ResumeFromInterpDescr(ResumeDescr): Modified: pypy/branch/fast-forward/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/executor.py Sun Jun 20 18:38:42 2010 @@ -2,248 +2,213 @@ """ import py -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, check_descr -from pypy.jit.metainterp.history import INT, REF, ConstFloat +from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, check_descr +from pypy.jit.metainterp.history import INT, REF, FLOAT, VOID, AbstractDescr from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop - - -# Operations in the _ALWAYS_PURE part of the table of resoperation.py -# must return a ConstInt or ConstPtr. Other operations must return -# a BoxInt or BoxPtr or None. +from pypy.jit.metainterp.blackhole import BlackholeInterpreter, NULL # ____________________________________________________________ -def do_int_add(cpu, box1, box2): - return ConstInt(intmask(box1.getint() + box2.getint())) - -def do_int_sub(cpu, box1, box2): - return ConstInt(intmask(box1.getint() - box2.getint())) - -def do_int_mul(cpu, box1, box2): - return ConstInt(intmask(box1.getint() * box2.getint())) - -def do_int_floordiv(cpu, box1, box2): - z = llop.int_floordiv(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_uint_floordiv(cpu, box1, box2): - z = llop.uint_floordiv(lltype.Unsigned, r_uint(box1.getint()), - r_uint(box2.getint())) - return ConstInt(intmask(z)) - -def do_int_mod(cpu, box1, box2): - z = llop.int_mod(lltype.Signed, box1.getint(), box2.getint()) - return ConstInt(z) - -def do_int_and(cpu, box1, box2): - return ConstInt(box1.getint() & box2.getint()) - -def do_int_or(cpu, box1, box2): - return ConstInt(box1.getint() | box2.getint()) - -def do_int_xor(cpu, box1, box2): - return ConstInt(box1.getint() ^ box2.getint()) - -def do_int_rshift(cpu, box1, box2): - return ConstInt(box1.getint() >> box2.getint()) - -def do_int_lshift(cpu, box1, box2): - return ConstInt(intmask(box1.getint() << box2.getint())) - -def do_uint_rshift(cpu, box1, box2): - v = r_uint(box1.getint()) >> r_uint(box2.getint()) - return ConstInt(intmask(v)) - -# ---------- - -def do_int_lt(cpu, box1, box2): - return ConstInt(box1.getint() < box2.getint()) - -def do_int_le(cpu, box1, box2): - return ConstInt(box1.getint() <= box2.getint()) - -def do_int_eq(cpu, box1, box2): - return ConstInt(box1.getint() == box2.getint()) - -def do_int_ne(cpu, box1, box2): - return ConstInt(box1.getint() != box2.getint()) - -def do_int_gt(cpu, box1, box2): - return ConstInt(box1.getint() > box2.getint()) - -def do_int_ge(cpu, box1, box2): - return ConstInt(box1.getint() >= box2.getint()) - -def do_uint_lt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) < r_uint(box2.getint())) - -def do_uint_le(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) <= r_uint(box2.getint())) - -def do_uint_gt(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) > r_uint(box2.getint())) - -def do_uint_ge(cpu, box1, box2): - return ConstInt(r_uint(box1.getint()) >= r_uint(box2.getint())) - -# ---------- - -def do_int_is_true(cpu, box1): - return ConstInt(bool(box1.getint())) - -def do_int_neg(cpu, box1): - return ConstInt(intmask(-box1.getint())) - -def do_int_invert(cpu, box1): - return ConstInt(~box1.getint()) - -def do_bool_not(cpu, box1): - return ConstInt(not box1.getint()) +def do_call(cpu, metainterp, argboxes, descr): + assert metainterp is not None + # count the number of arguments of the different types + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + type = argboxes[i].type + if type == INT: count_i += 1 + elif type == REF: count_r += 1 + elif type == FLOAT: count_f += 1 + # allocate lists for each type that has at least one argument + if count_i: args_i = [0] * count_i + else: args_i = None + if count_r: args_r = [NULL] * count_r + else: args_r = None + if count_f: args_f = [0.0] * count_f + else: args_f = None + # fill in the lists + count_i = count_r = count_f = 0 + for i in range(1, len(argboxes)): + box = argboxes[i] + if box.type == INT: + args_i[count_i] = box.getint() + count_i += 1 + elif box.type == REF: + args_r[count_r] = box.getref_base() + count_r += 1 + elif box.type == FLOAT: + args_f[count_f] = box.getfloat() + count_f += 1 + # get the function address as an integer + func = argboxes[0].getint() + # do the call using the correct function from the cpu + rettype = descr.get_return_type() + if rettype == INT: + try: + result = cpu.bh_call_i(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0 + return BoxInt(result) + if rettype == REF: + try: + result = cpu.bh_call_r(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = NULL + return BoxPtr(result) + if rettype == FLOAT: + try: + result = cpu.bh_call_f(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + result = 0.0 + return BoxFloat(result) + if rettype == VOID: + try: + cpu.bh_call_v(func, descr, args_i, args_r, args_f) + except Exception, e: + metainterp.execute_raised(e) + return None + raise AssertionError("bad rettype") + +do_call_loopinvariant = do_call +do_call_may_force = do_call + +def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + return BoxPtr(cpu.bh_getarrayitem_gc_r(arraydescr, array, index)) + elif arraydescr.is_array_of_floats(): + return BoxFloat(cpu.bh_getarrayitem_gc_f(arraydescr, array, index)) + else: + return BoxInt(cpu.bh_getarrayitem_gc_i(arraydescr, array, index)) -def do_same_as(cpu, box1): - return box1 +def do_setarrayitem_gc(cpu, _, arraybox, indexbox, itembox, arraydescr): + array = arraybox.getref_base() + index = indexbox.getint() + if arraydescr.is_array_of_pointers(): + cpu.bh_setarrayitem_gc_r(arraydescr, array, index, + itembox.getref_base()) + elif arraydescr.is_array_of_floats(): + cpu.bh_setarrayitem_gc_f(arraydescr, array, index, itembox.getfloat()) + else: + cpu.bh_setarrayitem_gc_i(arraydescr, array, index, itembox.getint()) -def do_oois(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() == box2.getint() - elif tp == REF: - x = box1.getref_base() == box2.getref_base() +def do_getfield_gc(cpu, _, structbox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr)) -def do_ooisnot(cpu, box1, box2): - tp = box1.type - assert tp == box2.type - if tp == INT: - x = box1.getint() != box2.getint() - elif tp == REF: - x = box1.getref_base() != box2.getref_base() +def do_getfield_raw(cpu, _, structbox, fielddescr): + check_descr(fielddescr) + struct = structbox.getint() + if fielddescr.is_pointer_field(): + return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr)) + elif fielddescr.is_float_field(): + return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr)) else: - assert False - return ConstInt(x) + return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr)) -def do_subclassof(cpu, box1, box2): - return ConstInt(cpu.ts.subclassOf(cpu, box1, box2)) +def do_setfield_gc(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getref_base() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_gc_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_gc_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_gc_i(struct, fielddescr, itembox.getint()) -# ---------- +def do_setfield_raw(cpu, _, structbox, itembox, fielddescr): + struct = structbox.getint() + if fielddescr.is_pointer_field(): + cpu.bh_setfield_raw_r(struct, fielddescr, itembox.getref_base()) + elif fielddescr.is_float_field(): + cpu.bh_setfield_raw_f(struct, fielddescr, itembox.getfloat()) + else: + cpu.bh_setfield_raw_i(struct, fielddescr, itembox.getint()) -def do_int_add_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def exec_new_with_vtable(cpu, clsbox): + from pypy.jit.codewriter import heaptracker + vtable = clsbox.getint() + descr = heaptracker.vtable2descr(cpu, vtable) + return cpu.bh_new_with_vtable(descr, vtable) + +def do_new_with_vtable(cpu, _, clsbox): + return BoxPtr(exec_new_with_vtable(cpu, clsbox)) + +def do_arraycopy(cpu, _, calldescr, funcbox, x1box, x2box, + x3box, x4box, x5box, arraydescr): + cpu.bh_call_v(funcbox.getint(), calldescr, + [x3box.getint(), x4box.getint(), x5box.getint()], + [x1box.getref_base(), x2box.getref_base()], None) + +def do_int_add_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x + y) + z = ovfcheck(a + b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_sub_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_sub_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x - y) + z = ovfcheck(a - b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -def do_int_mul_ovf(cpu, box1, box2): - x = box1.getint() - y = box2.getint() +def do_int_mul_ovf(cpu, metainterp, box1, box2): + assert metainterp is not None + a = box1.getint() + b = box2.getint() try: - z = ovfcheck(x * y) + z = ovfcheck(a * b) except OverflowError: - ovf = True + metainterp.execute_raised(OverflowError(), constant=True) z = 0 - else: - ovf = False - cpu._overflow_flag = ovf return BoxInt(z) -# ---------- - -def do_float_neg(cpu, box1): - return ConstFloat(-box1.getfloat()) - -def do_float_abs(cpu, box1): - return ConstFloat(abs(box1.getfloat())) - -def do_float_is_true(cpu, box1): - return ConstInt(bool(box1.getfloat())) - -def do_float_add(cpu, box1, box2): - return ConstFloat(box1.getfloat() + box2.getfloat()) - -def do_float_sub(cpu, box1, box2): - return ConstFloat(box1.getfloat() - box2.getfloat()) - -def do_float_mul(cpu, box1, box2): - return ConstFloat(box1.getfloat() * box2.getfloat()) - -def do_float_truediv(cpu, box1, box2): - return ConstFloat(box1.getfloat() / box2.getfloat()) - -def do_float_lt(cpu, box1, box2): - return ConstInt(box1.getfloat() < box2.getfloat()) - -def do_float_le(cpu, box1, box2): - return ConstInt(box1.getfloat() <= box2.getfloat()) - -def do_float_eq(cpu, box1, box2): - return ConstInt(box1.getfloat() == box2.getfloat()) - -def do_float_ne(cpu, box1, box2): - return ConstInt(box1.getfloat() != box2.getfloat()) - -def do_float_gt(cpu, box1, box2): - return ConstInt(box1.getfloat() > box2.getfloat()) - -def do_float_ge(cpu, box1, box2): - return ConstInt(box1.getfloat() >= box2.getfloat()) - -def do_cast_float_to_int(cpu, box1): - # note: we need to call int() twice to care for the fact that - # int(-2147483648.0) returns a long :-( - return ConstInt(int(int(box1.getfloat()))) - -def do_cast_int_to_float(cpu, box1): - return ConstFloat(float(box1.getint())) +def do_same_as(cpu, _, box): + return box.clonebox() # ____________________________________________________________ -def do_force_token(cpu): - raise NotImplementedError +##def do_force_token(cpu): +## raise NotImplementedError -def do_virtual_ref(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref(cpu, box1, box2): +## raise NotImplementedError -def do_virtual_ref_finish(cpu, box1, box2): - raise NotImplementedError +##def do_virtual_ref_finish(cpu, box1, box2): +## raise NotImplementedError -def do_debug_merge_point(cpu, box1): - from pypy.jit.metainterp.warmspot import get_stats - loc = box1._get_str() - get_stats().add_merge_point_location(loc) +##def do_debug_merge_point(cpu, box1): +## from pypy.jit.metainterp.warmspot import get_stats +## loc = box1._get_str() +## get_stats().add_merge_point_location(loc) # ____________________________________________________________ -def make_execute_list(cpuclass): - from pypy.jit.backend.model import AbstractCPU +def _make_execute_list(): if 0: # enable this to trace calls to do_xxx def wrap(fn): def myfn(*args): @@ -266,37 +231,109 @@ # find which list to store the operation in, based on num_args num_args = resoperation.oparity[value] withdescr = resoperation.opwithdescr[value] - if withdescr and num_args >= 0: - num_args += 1 - if num_args not in execute_by_num_args: - execute_by_num_args[num_args] = [None] * (rop._LAST+1) - execute = execute_by_num_args[num_args] + dictkey = num_args, withdescr + if dictkey not in execute_by_num_args: + execute_by_num_args[dictkey] = [None] * (rop._LAST+1) + execute = execute_by_num_args[dictkey] # if execute[value] is not None: - raise Exception("duplicate entry for op number %d" % value) + raise AssertionError("duplicate entry for op number %d"% value) + # + # Fish for a way for the pyjitpl interpreter to delegate + # really running the operation to the blackhole interpreter + # or directly to the cpu. First try the do_xxx() functions + # explicitly encoded above: + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # Maybe the same without the _PURE suffix? if key.endswith('_PURE'): key = key[:-5] - name = 'do_' + key.lower() - if hasattr(cpuclass, name): - execute[value] = wrap(getattr(cpuclass, name)) - elif name in globals(): - execute[value] = wrap(globals()[name]) - else: - assert hasattr(AbstractCPU, name), name - cpuclass._execute_by_num_args = execute_by_num_args + name = 'do_' + key.lower() + if name in globals(): + execute[value] = globals()[name] + continue + # + # If missing, fallback to the bhimpl_xxx() method of the + # blackhole interpreter. This only works if there is a + # method of the exact same name and it accepts simple + # parameters. + name = 'bhimpl_' + key.lower() + if hasattr(BlackholeInterpreter, name): + func = make_execute_function_with_boxes( + key.lower(), + getattr(BlackholeInterpreter, name).im_func) + if func is not None: + execute[value] = func + continue + if value in (rop.FORCE_TOKEN, + rop.CALL_ASSEMBLER, + rop.COND_CALL_GC_WB, + rop.DEBUG_MERGE_POINT, + rop.SETARRAYITEM_RAW, + ): # list of opcodes never executed by pyjitpl + continue + raise AssertionError("missing %r" % (key,)) + return execute_by_num_args +def make_execute_function_with_boxes(name, func): + # Make a wrapper for 'func'. The func is a simple bhimpl_xxx function + # from the BlackholeInterpreter class. The wrapper is a new function + # that receives and returns boxed values. + for argtype in func.argtypes: + if argtype not in ('i', 'r', 'f', 'd', 'cpu'): + return None + if list(func.argtypes).count('d') > 1: + return None + if func.resulttype not in ('i', 'r', 'f', None): + return None + argtypes = unrolling_iterable(func.argtypes) + resulttype = func.resulttype + # + def do(cpu, _, *argboxes): + newargs = () + for argtype in argtypes: + if argtype == 'cpu': + value = cpu + elif argtype == 'd': + value = argboxes[-1] + assert isinstance(value, AbstractDescr) + argboxes = argboxes[:-1] + else: + argbox = argboxes[0] + argboxes = argboxes[1:] + if argtype == 'i': value = argbox.getint() + elif argtype == 'r': value = argbox.getref_base() + elif argtype == 'f': value = argbox.getfloat() + newargs = newargs + (value,) + assert not argboxes + # + result = func(*newargs) + # + if resulttype == 'i': return BoxInt(result) + if resulttype == 'r': return BoxPtr(result) + if resulttype == 'f': return BoxFloat(result) + return None + # + do.func_name = 'do_' + name + return do -def get_execute_funclist(cpu, num_args): +def get_execute_funclist(num_args, withdescr): # workaround, similar to the next one - return cpu._execute_by_num_args[num_args] + return EXECUTE_BY_NUM_ARGS[num_args, withdescr] get_execute_funclist._annspecialcase_ = 'specialize:memo' -def get_execute_function(cpu, opnum, num_args): +def get_execute_function(opnum, num_args, withdescr): # workaround for an annotation limitation: putting this code in # a specialize:memo function makes sure the following line is # constant-folded away. Only works if opnum and num_args are # constants, of course. - return cpu._execute_by_num_args[num_args][opnum] + func = EXECUTE_BY_NUM_ARGS[num_args, withdescr][opnum] + assert func is not None, "EXECUTE_BY_NUM_ARGS[%s, %s][%s]" % ( + num_args, withdescr, resoperation.opname[opnum]) + return func get_execute_function._annspecialcase_ = 'specialize:memo' def has_descr(opnum): @@ -305,56 +342,61 @@ has_descr._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, descr, *argboxes): +def execute(cpu, metainterp, opnum, descr, *argboxes): # only for opnums with a fixed arity - if has_descr(opnum): + num_args = len(argboxes) + withdescr = has_descr(opnum) + if withdescr: check_descr(descr) argboxes = argboxes + (descr,) else: assert descr is None - func = get_execute_function(cpu, opnum, len(argboxes)) - assert func is not None - return func(cpu, *argboxes) -execute._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, num_args, withdescr) + return func(cpu, metainterp, *argboxes) # note that the 'argboxes' tuple + # optionally ends with the descr +execute._annspecialcase_ = 'specialize:arg(2)' -def execute_varargs(cpu, opnum, argboxes, descr): +def execute_varargs(cpu, metainterp, opnum, argboxes, descr): # only for opnums with a variable arity (calls, typically) check_descr(descr) - func = get_execute_function(cpu, opnum, -1) - assert func is not None - return func(cpu, argboxes, descr) -execute_varargs._annspecialcase_ = 'specialize:arg(1)' + func = get_execute_function(opnum, -1, True) + return func(cpu, metainterp, argboxes, descr) +execute_varargs._annspecialcase_ = 'specialize:arg(2)' -def execute_nonspec(cpu, opnum, argboxes, descr=None): +def execute_nonspec(cpu, metainterp, opnum, argboxes, descr=None): arity = resoperation.oparity[opnum] assert arity == -1 or len(argboxes) == arity if resoperation.opwithdescr[opnum]: check_descr(descr) if arity == -1: - func = get_execute_funclist(cpu, -1)[opnum] - return func(cpu, argboxes, descr) + func = get_execute_funclist(-1, True)[opnum] + return func(cpu, metainterp, argboxes, descr) if arity == 0: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, descr) + func = get_execute_funclist(0, True)[opnum] + return func(cpu, metainterp, descr) if arity == 1: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], descr) + func = get_execute_funclist(1, True)[opnum] + return func(cpu, metainterp, argboxes[0], descr) if arity == 2: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], descr) + func = get_execute_funclist(2, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], descr) if arity == 3: - func = get_execute_funclist(cpu, 4)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2], descr) + func = get_execute_funclist(3, True)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2], + descr) else: assert descr is None if arity == 1: - func = get_execute_funclist(cpu, 1)[opnum] - return func(cpu, argboxes[0]) + func = get_execute_funclist(1, False)[opnum] + return func(cpu, metainterp, argboxes[0]) if arity == 2: - func = get_execute_funclist(cpu, 2)[opnum] - return func(cpu, argboxes[0], argboxes[1]) + func = get_execute_funclist(2, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1]) if arity == 3: - func = get_execute_funclist(cpu, 3)[opnum] - return func(cpu, argboxes[0], argboxes[1], argboxes[2]) + func = get_execute_funclist(3, False)[opnum] + return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2]) raise NotImplementedError + + +EXECUTE_BY_NUM_ARGS = _make_execute_list() Modified: pypy/branch/fast-forward/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/history.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/history.py Sun Jun 20 18:38:42 2010 @@ -9,6 +9,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ @@ -16,6 +17,7 @@ REF = 'r' FLOAT = 'f' HOLE = '_' +VOID = 'v' FAILARGS_LIMIT = 1000 @@ -40,6 +42,7 @@ return "ref" else: raise NotImplementedError("type %s not supported" % TYPE) +getkind._annspecialcase_ = 'specialize:memo' def repr_pointer(box): from pypy.rpython.lltypesystem import rstr @@ -98,7 +101,7 @@ def nonconstbox(self): raise NotImplementedError - def getaddr(self, cpu): + def getaddr(self): raise NotImplementedError def sort_key(self): @@ -125,6 +128,18 @@ def _clone_if_mutable(self): return self + def get_arg_types(self): + """ Implement in call descr. + Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). + """ + raise NotImplementedError + + def get_return_type(self): + """ Implement in call descr. + Must return INT, REF, FLOAT, or 'v' for void. + """ + raise NotImplementedError + def get_extra_info(self): """ Implement in call descr """ @@ -150,6 +165,12 @@ """ raise NotImplementedError + def as_vtable_size_descr(self): + """ Implement for size descr representing objects with vtables. + Returns self. (it's an annotation hack) + """ + raise NotImplementedError + class AbstractFailDescr(AbstractDescr): index = -1 @@ -176,18 +197,13 @@ __slots__ = () @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": if isinstance(T, lltype.Ptr): - if not we_are_translated(): - # cannot store integers representing casted addresses - # inside ConstInt() instances that are going through - # translation; must use the special ConstAddr instead. - return ConstAddr(x, cpu) - intval = cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + intval = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x)) else: intval = lltype.cast_primitive(lltype.Signed, x) return ConstInt(intval) @@ -216,15 +232,13 @@ # to get the other behavior (i.e. using this __eq__). if self.__class__ is not other.__class__: return False - if isinstance(self.value, Symbolic): - v1 = "symbolic", id(self.value) - else: - v1 = self.value - if isinstance(other.value, Symbolic): - v2 = "symbolic", id(other.value) - else: - v2 = other.value - return v1 == v2 + try: + return self.value == other.value + except TypeError: + if (isinstance(self.value, Symbolic) and + isinstance(other.value, Symbolic)): + return self.value is other.value + raise def __ne__(self, other): return not (self == other) @@ -232,6 +246,7 @@ class ConstInt(Const): type = INT + value = 0 _attrs_ = ('value',) def __init__(self, value): @@ -250,11 +265,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -275,50 +290,6 @@ CONST_FALSE = ConstInt(0) CONST_TRUE = ConstInt(1) -class ConstAddr(Const): # only for constants built before translation - type = INT - _attrs_ = ('value', 'cpu') - - def __init__(self, adrvalue, cpu): - "NOT_RPYTHON" - assert not we_are_translated() - if isinstance(lltype.typeOf(adrvalue), lltype.Ptr): - adrvalue = llmemory.cast_ptr_to_adr(adrvalue) # convenience - else: - assert lltype.typeOf(adrvalue) == llmemory.Address - self.value = adrvalue - self.cpu = cpu - - def clonebox(self): - return BoxInt(self.cpu.cast_adr_to_int(self.value)) - - nonconstbox = clonebox - - def getint(self): - return self.cpu.cast_adr_to_int(self.value) - - def getaddr(self, cpu): - return self.value - - def _get_hash_(self): - return llmemory.cast_adr_to_int(self.value) - - def set_future_value(self, cpu, j): - cpu.set_future_value_int(j, self.getint()) - - def same_constant(self, other): - assert isinstance(other, Const) - return self.value == other.getaddr(self.cpu) - - def nonnull(self): - return bool(self.value) - - def _getrepr_(self): - return self.value - - def repr_rpython(self): - return repr_rpython(self, 'ca') - class ConstFloat(Const): type = FLOAT value = 0.0 @@ -355,6 +326,8 @@ def repr_rpython(self): return repr_rpython(self, 'cf') +CONST_FZERO = ConstFloat(0.0) + class ConstPtr(Const): type = REF value = lltype.nullptr(llmemory.GCREF.TO) @@ -382,7 +355,7 @@ else: return 0 - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def set_future_value(self, cpu, j): @@ -403,7 +376,13 @@ def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr - return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) + try: + return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), + self.value)) + except lltype.UninitializedMemoryAccess: + return '' + +CONST_NULL = ConstPtr(ConstPtr.value) class ConstObj(Const): type = REF @@ -435,7 +414,7 @@ def set_future_value(self, cpu, j): cpu.set_future_value_ref(j, self.value) -## def getaddr(self, cpu): +## def getaddr(self): ## # so far this is used only when calling ## # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a ## # real addr, but just a key for the dictionary @@ -464,7 +443,7 @@ is_box = True # hint that we want to make links in graphviz from this @staticmethod - def _new(x, cpu): + def _new(x): "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": @@ -527,11 +506,11 @@ def getint(self): return self.value - def getaddr(self, cpu): - return cpu.cast_int_to_adr(self.value) + def getaddr(self): + return heaptracker.int2adr(self.value) def _get_hash_(self): - return self.value + return make_hashable_int(self.value) def set_future_value(self, cpu, j): cpu.set_future_value_int(j, self.value) @@ -598,7 +577,7 @@ return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' - def getaddr(self, cpu): + def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def _get_hash_(self): @@ -694,6 +673,13 @@ except lltype.DelayedPointer: return -2 # xxx risk of changing hash... +def make_hashable_int(i): + if not we_are_translated() and isinstance(i, llmemory.AddressAsInt): + # Warning: such a hash changes at the time of translation + adr = heaptracker.int2adr(i) + return llmemory.cast_adr_to_int(adr, "emulated") + return i + # ____________________________________________________________ # The TreeLoop class contains a loop or a generalized loop, i.e. a tree @@ -845,16 +831,6 @@ op = ResOperation(opnum, argboxes, resbox, descr) self.operations[position] = op - def slice_history_at(self, position): - """ a strange function that does this: - history : operation_at_position : rest - it'll kill operation_at_position, store everything before that - in history.operations and return rest - """ - rest = self.operations[position + 1:] - del self.operations[position:] - return rest - # ____________________________________________________________ Modified: pypy/branch/fast-forward/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/jitprof.py Sun Jun 20 18:38:42 2010 @@ -5,6 +5,7 @@ import os import time from pypy.rlib.debug import debug_print +from pypy.jit.metainterp.jitexc import JitException counters=""" TRACING @@ -13,7 +14,6 @@ BLACKHOLE OPS RECORDED_OPS -BLACKHOLED_OPS GUARDS OPT_OPS OPT_GUARDS @@ -34,7 +34,7 @@ ncounters = len(names) _setup() -JITPROF_LINES = ncounters + 1 + 5 # one for TOTAL, 5 for calls, update if needed +JITPROF_LINES = ncounters + 1 + 1 # one for TOTAL, 1 for calls, update if needed class BaseProfiler(object): pass @@ -88,7 +88,7 @@ t1 = 0 times = None counters = None - calls = None + calls = 0 current = None printing = True @@ -97,7 +97,7 @@ self.t1 = self.starttime self.times = [0, 0] self.counters = [0] * ncounters - self.calls = [[0, 0], [0, 0], [0, 0]] + self.calls = 0 self.current = [] def finish(self): @@ -150,10 +150,8 @@ def count_ops(self, opnum, kind=OPS): from pypy.jit.metainterp.resoperation import rop self.counters[kind] += 1 - if opnum == rop.CALL or opnum == rop.OOSEND: - self.calls[kind-OPS][0] += 1 - elif opnum == rop.CALL_PURE or opnum == rop.OOSEND_PURE: - self.calls[kind-OPS][1] += 1 + if opnum == rop.CALL and kind == RECORDED_OPS:# or opnum == rop.OOSEND: + self.calls += 1 def print_stats(self): cnt = self.counters @@ -166,14 +164,9 @@ line = "TOTAL: \t\t%f\n" % (self.tk - self.starttime, ) os.write(2, line) self._print_intline("ops", cnt[OPS]) - self._print_intline(" calls", calls[0][0]) - self._print_intline(" pure calls", calls[0][1]) self._print_intline("recorded ops", cnt[RECORDED_OPS]) - self._print_intline(" calls", calls[1][0]) - self._print_intline(" pure calls", calls[1][1]) + self._print_intline(" calls", calls) self._print_intline("guards", cnt[GUARDS]) - self._print_intline("blackholed ops", calls[2][0]) - self._print_intline(" pure calls", calls[2][1]) self._print_intline("opt ops", cnt[OPT_OPS]) self._print_intline("opt guards", cnt[OPT_GUARDS]) self._print_intline("forcings", cnt[OPT_FORCINGS]) @@ -195,5 +188,5 @@ -class BrokenProfilerData(Exception): +class BrokenProfilerData(JitException): pass Modified: pypy/branch/fast-forward/pypy/jit/metainterp/logger.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/logger.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/logger.py Sun Jun 20 18:38:42 2010 @@ -1,9 +1,11 @@ import os from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, \ - BoxInt, ConstAddr, ConstFloat, BoxFloat, AbstractFailDescr + BoxInt, ConstFloat, BoxFloat, AbstractFailDescr class Logger(object): @@ -46,10 +48,16 @@ mv = len(memo) memo[arg] = mv if isinstance(arg, ConstInt): + if int_could_be_an_address(arg.value): + addr = arg.getaddr() + name = self.metainterp_sd.get_name_from_address(addr) + if name: + return 'ConstClass(' + name + ')' return str(arg.value) elif isinstance(arg, BoxInt): return 'i' + str(mv) elif isinstance(arg, self.ts.ConstRef): + # XXX for ootype, this should also go through get_name_from_address return 'ConstPtr(ptr' + str(mv) + ')' elif isinstance(arg, self.ts.BoxRef): return 'p' + str(mv) @@ -57,12 +65,6 @@ return str(arg.value) elif isinstance(arg, BoxFloat): return 'f' + str(mv) - elif isinstance(arg, self.ts.ConstAddr): - addr = arg.getaddr(self.metainterp_sd.cpu) - name = self.metainterp_sd.get_name_from_address(addr) - if not name: - name = 'cls' + str(mv) - return 'ConstClass(' + name + ')' elif arg is None: return 'None' else: @@ -102,3 +104,11 @@ fail_args = '' debug_print(res + op.getopname() + '(' + args + ')' + fail_args) + + +def int_could_be_an_address(x): + if we_are_translated(): + x = rffi.cast(lltype.Signed, x) # force it + return not (-32768 <= x <= 32767) + else: + return isinstance(x, llmemory.AddressAsInt) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizefindnode.py Sun Jun 20 18:38:42 2010 @@ -160,7 +160,8 @@ else: # all constant arguments: we can constant-fold argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.set_constant_node(op.result, resbox.constbox()) # default case: mark the arguments as escaping for box in op.args: @@ -169,8 +170,8 @@ def find_nodes_no_escape(self, op): pass # for operations that don't escape their arguments - find_nodes_OOIS = find_nodes_no_escape - find_nodes_OOISNOT = find_nodes_no_escape + find_nodes_PTR_EQ = find_nodes_no_escape + find_nodes_PTR_NE = find_nodes_no_escape find_nodes_INSTANCEOF = find_nodes_no_escape find_nodes_GUARD_NONNULL = find_nodes_no_escape find_nodes_GUARD_ISNULL = find_nodes_no_escape Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt.py Sun Jun 20 18:38:42 2010 @@ -16,7 +16,7 @@ from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype -from pypy.jit.metainterp.history import AbstractDescr +from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int def optimize_loop_1(metainterp_sd, loop): """Optimize loop.operations to make it match the input of loop.specnodes @@ -89,7 +89,7 @@ if level == LEVEL_KNOWNCLASS: return self.known_class elif level == LEVEL_CONSTANT: - return cpu.ts.cls_of_box(cpu, self.box) + return cpu.ts.cls_of_box(self.box) else: return None @@ -554,7 +554,7 @@ elif op.can_raise(): self.exception_might_have_happened = True elif op.returns_bool_result(): - self.bool_boxes[op.result] = None + self.bool_boxes[self.getvalue(op.result)] = None self.newoperations.append(op) def store_final_boxes_in_guard(self, op): @@ -564,11 +564,11 @@ modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) newboxes = modifier.finish(self.values, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here - raise compile.GiveUp + compile.giveup() descr.store_final_boxes(op, newboxes) # if op.opnum == rop.GUARD_VALUE: - if op.args[0] in self.bool_boxes: + if self.getvalue(op.args[0]) in self.bool_boxes: # Hack: turn guard_value(bool) into guard_true/guard_false. # This is done after the operation is emitted, to let # store_final_boxes_in_guard set the guard_opnum field @@ -594,7 +594,8 @@ else: # all constant arguments: constant-fold away argboxes = [self.get_constant_box(arg) for arg in op.args] - resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr) + resbox = execute_nonspec(self.cpu, None, + op.opnum, argboxes, op.descr) self.make_constant(op.result, resbox.constbox()) return @@ -745,8 +746,14 @@ self.optimize_default(op) def optimize_INT_IS_TRUE(self, op): + if self.getvalue(op.args[0]) in self.bool_boxes: + self.make_equal_to(op.result, self.getvalue(op.args[0])) + return self._optimize_nullness(op, op.args[0], True) + def optimize_INT_IS_ZERO(self, op): + self._optimize_nullness(op, op.args[0], False) + def _optimize_oois_ooisnot(self, op, expect_isnot): value0 = self.getvalue(op.args[0]) value1 = self.getvalue(op.args[1]) @@ -775,10 +782,10 @@ return self.optimize_default(op) - def optimize_OOISNOT(self, op): + def optimize_PTR_NE(self, op): self._optimize_oois_ooisnot(op, True) - def optimize_OOIS(self, op): + def optimize_PTR_EQ(self, op): self._optimize_oois_ooisnot(op, False) def optimize_VIRTUAL_REF(self, op): @@ -944,7 +951,8 @@ if not funcvalue.is_constant(): self.optimize_default(op) return - resvalue = self.loop_invariant_results.get(op.args[0].getint(), None) + key = make_hashable_int(op.args[0].getint()) + resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: self.make_equal_to(op.result, resvalue) return @@ -953,7 +961,19 @@ op.opnum = rop.CALL self.optimize_default(op) resvalue = self.getvalue(op.result) - self.loop_invariant_results[op.args[0].getint()] = resvalue + self.loop_invariant_results[key] = resvalue + + def optimize_CALL_PURE(self, op): + for arg in op.args: + if self.get_constant_box(arg) is None: + break + else: + # all constant arguments: constant-fold away + self.make_constant(op.result, op.args[0]) + return + # replace CALL_PURE with just CALL + self.emit_operation(ResOperation(rop.CALL, op.args[1:], op.result, + op.descr)) def optimize_INT_AND(self, op): v1 = self.getvalue(op.args[0]) @@ -1066,7 +1086,7 @@ return None def emitting_operation(self, op): - if op.opnum != rop.CALL_PURE and op.has_no_side_effect(): + if op.has_no_side_effect(): return if op.is_ovf(): return @@ -1077,9 +1097,9 @@ opnum == rop.SETARRAYITEM_GC or opnum == rop.DEBUG_MERGE_POINT): return + assert opnum != rop.CALL_PURE if (opnum == rop.CALL or opnum == rop.CALL_MAY_FORCE or - opnum == rop.CALL_PURE or opnum == rop.CALL_ASSEMBLER): if opnum == rop.CALL_ASSEMBLER: effectinfo = None @@ -1101,7 +1121,7 @@ del self.cached_arrayitems[arraydescr] except KeyError: pass - if effectinfo.forces_virtual_or_virtualizable: + if effectinfo.check_forces_virtual_or_virtualizable(): vrefinfo = self.optimizer.metainterp_sd.virtualref_info self.force_lazy_setfield(vrefinfo.descr_forced) # ^^^ we only need to force this field; the other fields Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeutil.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeutil.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeutil.py Sun Jun 20 18:38:42 2010 @@ -2,8 +2,9 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp import resoperation, history +from pypy.jit.metainterp.jitexc import JitException -class InvalidLoop(Exception): +class InvalidLoop(JitException): """Raised when the optimize*.py detect that the loop that we are trying to build cannot possibly make sense as a long-running loop (e.g. it cannot run 2 complete iterations).""" Modified: pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py Sun Jun 20 18:38:42 2010 @@ -1,205 +1,170 @@ import py, os -from pypy.rpython.lltypesystem import llmemory -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_start, debug_stop, debug_print +from pypy.rlib.debug import make_sure_not_resized +from pypy.rlib import nonconst from pypy.jit.metainterp import history, compile, resume -from pypy.jit.metainterp.history import Const, ConstInt, Box +from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat +from pypy.jit.metainterp.history import Box from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp import codewriter, executor +from pypy.jit.metainterp import executor from pypy.jit.metainterp.logger import Logger -from pypy.jit.metainterp.jitprof import BLACKHOLED_OPS, EmptyProfiler +from pypy.jit.metainterp.jitprof import EmptyProfiler from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE +from pypy.jit.metainterp.jitexc import JitException, get_llexception from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED -from pypy.jit.metainterp.compile import GiveUp +from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from pypy.jit.codewriter import heaptracker # ____________________________________________________________ -def check_args(*args): - for arg in args: - assert isinstance(arg, (Box, Const)) - -class arguments(object): - def __init__(self, *argtypes): - self.argtypes = argtypes - - def __eq__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes == other.argtypes - - def __ne__(self, other): - if not isinstance(other, arguments): - return NotImplemented - return self.argtypes != other.argtypes - - def __call__(self, func): - argtypes = unrolling_iterable(self.argtypes) - def wrapped(self, orgpc): - args = (self, ) - for argspec in argtypes: - if argspec == "box": - box = self.load_arg() - args += (box, ) - elif argspec == "constbox": - args += (self.load_const_arg(), ) - elif argspec == "int": - args += (self.load_int(), ) - elif argspec == "jumptarget": - args += (self.load_3byte(), ) - elif argspec == "jumptargets": - num = self.load_int() - args += ([self.load_3byte() for i in range(num)], ) - elif argspec == "varargs": - args += (self.load_varargs(), ) - elif argspec == "constargs": - args += (self.load_constargs(), ) - elif argspec == "descr": - descr = self.load_const_arg() - assert isinstance(descr, history.AbstractDescr) - args += (descr, ) - elif argspec == "bytecode": - bytecode = self.load_const_arg() - assert isinstance(bytecode, codewriter.JitCode) - args += (bytecode, ) - elif argspec == "orgpc": - args += (orgpc, ) - elif argspec == "methdescr": - methdescr = self.load_const_arg() - assert isinstance(methdescr, - history.AbstractMethDescr) - args += (methdescr, ) - else: - assert 0, "unknown argtype declaration: %r" % (argspec,) - val = func(*args) - if val is None: - val = False - return val - name = func.func_name - wrapped.func_name = "wrap_" + name - wrapped.argspec = self - return wrapped +def arguments(*args): + def decorate(func): + func.argtypes = args + return func + return decorate # ____________________________________________________________ class MIFrame(object): - exception_box = None - exc_value_box = None - # for resume.py operation - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - def __init__(self, metainterp, jitcode, greenkey=None): - assert isinstance(jitcode, codewriter.JitCode) + def __init__(self, metainterp): self.metainterp = metainterp + self.registers_i = [None] * 256 + self.registers_r = [None] * 256 + self.registers_f = [None] * 256 + + def setup(self, jitcode, greenkey=None): + assert isinstance(jitcode, JitCode) self.jitcode = jitcode self.bytecode = jitcode.code - self.constants = jitcode.constants - self.exception_target = -1 - self.name = jitcode.name # purely for having name attribute # this is not None for frames that are recursive portal calls self.greenkey = greenkey + # copy the constants in place + self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt) + self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr) + self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat) + self._result_argcode = 'v' + # for resume.py operation + self.parent_resumedata_snapshot = None + self.parent_resumedata_frame_info_list = None + + def copy_constants(self, registers, constants, ConstClass): + """Copy jitcode.constants[0] to registers[255], + jitcode.constants[1] to registers[254], + jitcode.constants[2] to registers[253], etc.""" + if nonconst.NonConstant(0): # force the right type + constants[0] = ConstClass.value # (useful for small tests) + i = len(constants) - 1 + while i >= 0: + j = 255 - i + assert j >= 0 + registers[j] = ConstClass(constants[i]) + i -= 1 + copy_constants._annspecialcase_ = 'specialize:arg(3)' + + def cleanup_registers(self): + # To avoid keeping references alive, this cleans up the registers_r. + # It does not clear the references set by copy_constants(), but + # these are all prebuilt constants anyway. + for i in range(self.jitcode.num_regs_r()): + self.registers_r[i] = None # ------------------------------ # Decoding of the JitCode - def load_int(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - if result > 0x7F: - result = self._load_larger_int(result) - return result - - def _load_larger_int(self, result): # slow path - result = result & 0x7F - shift = 7 - pc = self.pc - while 1: - byte = ord(self.bytecode[pc]) - pc += 1 - result += (byte & 0x7F) << shift - shift += 7 - if not byte & 0x80: - break - self.pc = pc - return intmask(result) - _load_larger_int._dont_inline_ = True - - def load_3byte(self): - pc = self.pc - result = (((ord(self.bytecode[pc + 0])) << 16) | - ((ord(self.bytecode[pc + 1])) << 8) | - ((ord(self.bytecode[pc + 2])) << 0)) - self.pc = pc + 3 - return result - - def load_bool(self): - pc = self.pc - result = ord(self.bytecode[pc]) - self.pc = pc + 1 - return bool(result) - - def getenv(self, i): - assert i >= 0 - j = i >> 1 - if i & 1: - return self.constants[j] - else: - assert j < len(self.env) - return self.env[j] - - def load_arg(self): - return self.getenv(self.load_int()) - - def load_const_arg(self): - return self.constants[self.load_int()] - - def load_varargs(self): - count = self.load_int() - return [self.load_arg() for i in range(count)] - - def load_constargs(self): - count = self.load_int() - return [self.load_const_arg() for i in range(count)] - - def ignore_varargs(self): - count = self.load_int() + def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): + assert argcode in 'IRF' + code = self.bytecode + length = ord(code[position]) + position += 1 + for i in range(length): + index = ord(code[position+i]) + if argcode == 'I': reg = self.registers_i[index] + elif argcode == 'R': reg = self.registers_r[index] + elif argcode == 'F': reg = self.registers_f[index] + else: raise AssertionError(argcode) + outvalue[startindex+i] = reg + prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' + + def get_current_position_info(self): + return self.jitcode.get_live_vars_info(self.pc) + + def get_list_of_active_boxes(self, in_a_call): + if in_a_call: + # If we are not the topmost frame, self._result_argcode contains + # the type of the result of the call instruction in the bytecode. + # We use it to clear the box that will hold the result: this box + # is not defined yet. + argcode = self._result_argcode + index = ord(self.bytecode[self.pc - 1]) + if argcode == 'i': self.registers_i[index] = history.CONST_FALSE + elif argcode == 'r': self.registers_r[index] = history.CONST_NULL + elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO + self._result_argcode = '?' # done + # + info = self.get_current_position_info() + start_i = 0 + start_r = start_i + info.get_register_count_i() + start_f = start_r + info.get_register_count_r() + total = start_f + info.get_register_count_f() + # allocate a list of the correct size + env = [None] * total + make_sure_not_resized(env) + # fill it now + for i in range(info.get_register_count_i()): + index = info.get_register_index_i(i) + env[start_i + i] = self.registers_i[index] + for i in range(info.get_register_count_r()): + index = info.get_register_index_r(i) + env[start_r + i] = self.registers_r[index] + for i in range(info.get_register_count_f()): + index = info.get_register_index_f(i) + env[start_f + i] = self.registers_f[index] + return env + + def replace_active_box_in_frame(self, oldbox, newbox): + if isinstance(oldbox, history.BoxInt): + count = self.jitcode.num_regs_i() + registers = self.registers_i + elif isinstance(oldbox, history.BoxPtr): + count = self.jitcode.num_regs_r() + registers = self.registers_r + elif isinstance(oldbox, history.BoxFloat): + count = self.jitcode.num_regs_f() + registers = self.registers_f + else: + assert 0, oldbox for i in range(count): - self.load_int() - - def getvarenv(self, i): - return self.env[i] + if registers[i] is oldbox: + registers[i] = newbox + if not we_are_translated(): + assert oldbox not in registers[count:] - def make_result_box(self, box): - assert isinstance(box, Box) or isinstance(box, Const) - self.env.append(box) + def make_result_of_lastop(self, resultbox): + if resultbox is None: + return + target_index = ord(self.bytecode[self.pc-1]) + if resultbox.type == history.INT: + self.registers_i[target_index] = resultbox + elif resultbox.type == history.REF: + #debug_print(' ->', + # llmemory.cast_ptr_to_adr(resultbox.getref_base())) + self.registers_r[target_index] = resultbox + elif resultbox.type == history.FLOAT: + self.registers_f[target_index] = resultbox + else: + raise AssertionError("bad result box type") # ------------------------------ - for _n in range(codewriter.MAX_MAKE_NEW_VARS): - _decl = ', '.join(["'box'" for _i in range(_n)]) - _allargs = ', '.join(["box%d" % _i for _i in range(_n)]) - exec py.code.Source(""" - @arguments(%s) - def opimpl_make_new_vars_%d(self, %s): - if not we_are_translated(): - check_args(%s) - self.env = [%s] - """ % (_decl, _n, _allargs, _allargs, _allargs)).compile() - - @arguments("varargs") - def opimpl_make_new_vars(self, newenv): - if not we_are_translated(): - check_args(*newenv) - self.env = newenv - for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod', 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', @@ -210,175 +175,251 @@ 'float_add', 'float_sub', 'float_mul', 'float_truediv', 'float_lt', 'float_le', 'float_eq', 'float_ne', 'float_gt', 'float_ge', + 'ptr_eq', 'ptr_ne', ]: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) + return self.execute(rop.%s, b1, b2) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, b1, b2) - return self.metainterp.handle_overflow_error() + self.metainterp.clear_exception() + resbox = self.execute(rop.%s, b1, b2) + self.make_result_of_lastop(resbox) # same as execute_varargs() + self.metainterp.handle_possible_overflow_error() + return resbox ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', - 'cast_ptr_to_int', 'cast_float_to_int', - 'cast_int_to_float', 'float_neg', 'float_abs', - 'float_is_true', + for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert', + 'cast_float_to_int', 'cast_int_to_float', + 'float_neg', 'float_abs', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, b) + return self.execute(rop.%s, b) ''' % (_opimpl, _opimpl.upper())).compile() - @arguments() - def opimpl_return(self): - assert len(self.env) == 1 - return self.metainterp.finishframe(self.env[0]) + @arguments("box") + def opimpl_ptr_nonzero(self, box): + return self.execute(rop.PTR_NE, box, history.CONST_NULL) + + @arguments("box") + def opimpl_ptr_iszero(self, box): + return self.execute(rop.PTR_EQ, box, history.CONST_NULL) + + @arguments("box") + def _opimpl_any_return(self, box): + self.metainterp.finishframe(box) + + opimpl_int_return = _opimpl_any_return + opimpl_ref_return = _opimpl_any_return + opimpl_float_return = _opimpl_any_return @arguments() def opimpl_void_return(self): - assert len(self.env) == 0 - return self.metainterp.finishframe(None) + self.metainterp.finishframe(None) + + @arguments("box") + def _opimpl_any_copy(self, box): + return box + + opimpl_int_copy = _opimpl_any_copy + opimpl_ref_copy = _opimpl_any_copy + opimpl_float_copy = _opimpl_any_copy + + @arguments("box") + def _opimpl_any_push(self, box): + self.pushed_box = box + + opimpl_int_push = _opimpl_any_push + opimpl_ref_push = _opimpl_any_push + opimpl_float_push = _opimpl_any_push - @arguments("jumptarget") + @arguments() + def _opimpl_any_pop(self): + box = self.pushed_box + self.pushed_box = None + return box + + opimpl_int_pop = _opimpl_any_pop + opimpl_ref_pop = _opimpl_any_pop + opimpl_float_pop = _opimpl_any_pop + + @arguments("label") + def opimpl_catch_exception(self, target): + """This is a no-op when run normally. We can check that + last_exc_value_box is None; it should have been set to None + by the previous instruction. If the previous instruction + raised instead, finishframe_exception() should have been + called and we would not be there.""" + assert self.metainterp.last_exc_value_box is None + + @arguments("label") def opimpl_goto(self, target): self.pc = target - @arguments("orgpc", "jumptarget", "box", "varargs") - def opimpl_goto_if_not(self, pc, target, box, livelist): + @arguments("box", "label") + def opimpl_goto_if_not(self, box, target): switchcase = box.getint() if switchcase: opnum = rop.GUARD_TRUE else: - self.pc = target opnum = rop.GUARD_FALSE - self.env = livelist - self.generate_guard(pc, opnum, box) - # note about handling self.env explicitly here: it is done in - # such a way that the 'box' on which we generate the guard is - # typically not included in the livelist. - - def follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - target = self.load_3byte() # load the 'target' argument - self.pc = target # jump - - def ignore_next_guard_nullness(self, opnum): - _op_ooisnull = self.metainterp.staticdata._op_ooisnull - _op_oononnull = self.metainterp.staticdata._op_oononnull - bc = ord(self.bytecode[self.pc]) - if bc == _op_ooisnull: - if opnum == rop.GUARD_ISNULL: - res = ConstInt(0) - else: - res = ConstInt(1) + self.generate_guard(opnum, box) + if not switchcase: + self.pc = target + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_true(self, box, target): + condbox = self.execute(rop.INT_IS_TRUE, box) + self.opimpl_goto_if_not(condbox, target) + + @arguments("box", "label") + def opimpl_goto_if_not_int_is_zero(self, box, target): + condbox = self.execute(rop.INT_IS_ZERO, box) + self.opimpl_goto_if_not(condbox, target) + + for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', + 'ptr_eq', 'ptr_ne']: + exec py.code.Source(''' + @arguments("box", "box", "label") + def opimpl_goto_if_not_%s(self, b1, b2, target): + condbox = self.execute(rop.%s, b1, b2) + self.opimpl_goto_if_not(condbox, target) + ''' % (_opimpl, _opimpl.upper())).compile() + + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL else: - assert bc == _op_oononnull - if opnum == rop.GUARD_ISNULL: - res = ConstInt(1) - else: - res = ConstInt(0) - self.pc += 1 # past the bytecode for ptr_iszero/ptr_nonzero - self.load_int() # past the 'box' argument - self.make_result_box(res) - - def dont_follow_jump(self): - _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not - assert ord(self.bytecode[self.pc]) == _op_goto_if_not - self.pc += 1 # past the bytecode for 'goto_if_not' - self.load_3byte() # past the 'target' argument - self.load_int() # past the 'box' argument - self.ignore_varargs() # past the 'livelist' argument - - @arguments("orgpc", "box", "constargs", "jumptargets") - def opimpl_switch(self, pc, valuebox, constargs, jumptargets): - box = self.implement_guard_value(pc, valuebox) - for i in range(len(constargs)): - casebox = constargs[i] - if box.same_constant(casebox): - self.pc = jumptargets[i] - break + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if not value: + self.pc = target - @arguments("orgpc", "box", "constbox") - def opimpl_switch_dict(self, pc, valuebox, switchdict): - box = self.implement_guard_value(pc, valuebox) + @arguments("orgpc", "box", "label") + def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target): + value = box.nonnull() + if value: + opnum = rop.GUARD_NONNULL + else: + opnum = rop.GUARD_ISNULL + self.generate_guard(opnum, box, resumepc=orgpc) + if value: + self.pc = target + + @arguments("box", "box", "box") + def opimpl_int_between(self, b1, b2, b3): + b5 = self.execute(rop.INT_SUB, b3, b1) + if isinstance(b5, ConstInt) and b5.getint() == 1: + # the common case of int_between(a, b, a+1) turns into just INT_EQ + return self.execute(rop.INT_EQ, b2, b1) + else: + b4 = self.execute(rop.INT_SUB, b2, b1) + return self.execute(rop.UINT_LT, b4, b5) + + @arguments("box", "descr", "orgpc") + def opimpl_switch(self, valuebox, switchdict, orgpc): + box = self.implement_guard_value(orgpc, valuebox) search_value = box.getint() - assert isinstance(switchdict, codewriter.SwitchDict) + assert isinstance(switchdict, SwitchDictDescr) try: self.pc = switchdict.dict[search_value] except KeyError: pass - @arguments("descr") - def opimpl_new(self, size): - self.execute_with_descr(rop.NEW, descr=size) - - @arguments("constbox") - def opimpl_new_with_vtable(self, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, vtablebox) + @arguments() + def opimpl_unreachable(self): + raise AssertionError("unreachable") - @arguments("box") - def opimpl_runtimenew(self, classbox): - self.execute(rop.RUNTIMENEW, classbox) + @arguments("descr") + def opimpl_new(self, sizedescr): + return self.execute_with_descr(rop.NEW, sizedescr) - @arguments("orgpc", "box", "descr") - def opimpl_instanceof(self, pc, objbox, typedescr): - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + @arguments("descr") + def opimpl_new_with_vtable(self, sizedescr): + cpu = self.metainterp.cpu + cls = heaptracker.descr2vtable(cpu, sizedescr) + return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls)) - @arguments("box", "box") - def opimpl_subclassof(self, box1, box2): - self.execute(rop.SUBCLASSOF, box1, box2) +## @FixME #arguments("box") +## def opimpl_runtimenew(self, classbox): +## self.execute(rop.RUNTIMENEW, classbox) + +## @FixME #arguments("orgpc", "box", "descr") +## def opimpl_instanceof(self, pc, objbox, typedescr): +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## self.execute_with_descr(rop.INSTANCEOF, typedescr, objbox) + +## @FixME #arguments("box", "box") +## def opimpl_subclassof(self, box1, box2): +## self.execute(rop.SUBCLASSOF, box1, box2) @arguments("descr", "box") - def opimpl_new_array(self, itemsize, countbox): - self.execute_with_descr(rop.NEW_ARRAY, itemsize, countbox) + def opimpl_new_array(self, itemsizedescr, countbox): + return self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, countbox) @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any + opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any @arguments("box", "descr", "box") - def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, arraydesc, arraybox, indexbox) + def _opimpl_getarrayitem_gc_pure_any(self, arraybox, arraydescr, indexbox): + return self.execute_with_descr(rop.GETARRAYITEM_GC_PURE, + arraydescr, arraybox, indexbox) + + opimpl_getarrayitem_gc_pure_i = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_r = _opimpl_getarrayitem_gc_pure_any + opimpl_getarrayitem_gc_pure_f = _opimpl_getarrayitem_gc_pure_any @arguments("box", "descr", "box", "box") - def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydesc, arraybox, indexbox, itembox) + def _opimpl_setarrayitem_gc_any(self, arraybox, arraydescr, + indexbox, itembox): + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, itembox) + + opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any + opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any @arguments("box", "descr") - def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute_with_descr(rop.ARRAYLEN_GC, arraydesc, arraybox) + def opimpl_arraylen_gc(self, arraybox, arraydescr): + return self.execute_with_descr(rop.ARRAYLEN_GC, arraydescr, arraybox) @arguments("descr", "box", "box", "box", "box", "box", "box", "descr") def opimpl_arraycopy(self, calldescr, fnptr, sourcebox, destbox, - source_startbox, dest_startbox, lengthbox, arraydescr): + source_startbox, dest_startbox, lengthbox, + arraydescr): self.execute_with_descr(rop.ARRAYCOPY, arraydescr, calldescr, fnptr, sourcebox, destbox, source_startbox, dest_startbox, lengthbox) @arguments("orgpc", "box", "descr", "box") - def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): + def opimpl_check_neg_index(self, orgpc, arraybox, arraydescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, arraydesc, arraybox) + rop.ARRAYLEN_GC, arraydescr, arraybox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) + return indexbox @arguments("descr", "descr", "descr", "descr", "box") def opimpl_newlist(self, structdescr, lengthdescr, itemsdescr, arraydescr, @@ -390,131 +431,87 @@ sizebox) self.metainterp.execute_and_record(rop.SETFIELD_GC, itemsdescr, sbox, abox) - self.make_result_box(sbox) + return sbox @arguments("box", "descr", "descr", "box") - def opimpl_getlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox): + def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.GETARRAYITEM_GC, arraydescr, arraybox, indexbox) + return self.execute_with_descr(rop.GETARRAYITEM_GC, + arraydescr, arraybox, indexbox) + + opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any + opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any @arguments("box", "descr", "descr", "box", "box") - def opimpl_setlistitem_gc(self, listbox, itemsdescr, arraydescr, indexbox, - valuebox): + def _opimpl_setlistitem_gc_any(self, listbox, itemsdescr, arraydescr, + indexbox, valuebox): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, itemsdescr, listbox) - self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, indexbox, valuebox) + self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox, + indexbox, valuebox) + + opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any + opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any @arguments("orgpc", "box", "descr", "box") - def opimpl_check_resizable_neg_index(self, pc, listbox, lengthdesc, + def opimpl_check_resizable_neg_index(self, orgpc, listbox, lengthdescr, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, None, indexbox, ConstInt(0)) - negbox = self.implement_guard_value(pc, negbox) + rop.INT_LT, None, indexbox, history.CONST_FALSE) + negbox = self.implement_guard_value(orgpc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.GETFIELD_GC, lengthdesc, listbox) + rop.GETFIELD_GC, lengthdescr, listbox) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, None, indexbox, lenbox) - self.make_result_box(indexbox) - - @arguments("orgpc", "box") - def opimpl_check_zerodivisionerror(self, pc, box): - nonzerobox = self.metainterp.execute_and_record( - rop.INT_NE, None, box, ConstInt(0)) - nonzerobox = self.implement_guard_value(pc, nonzerobox) - if nonzerobox.getint(): - return False - else: - # division by zero! - return self.metainterp.raise_zero_division_error() - - @arguments("orgpc", "box", "box") - def opimpl_check_div_overflow(self, pc, box1, box2): - # detect the combination "box1 = -sys.maxint-1, box2 = -1". - import sys - tmp1 = self.metainterp.execute_and_record( # combination to detect: - rop.INT_ADD, None, box1, ConstInt(sys.maxint)) # tmp1=-1, box2=-1 - tmp2 = self.metainterp.execute_and_record( - rop.INT_AND, None, tmp1, box2) # tmp2=-1 - tmp3 = self.metainterp.execute_and_record( - rop.INT_EQ, None, tmp2, ConstInt(-1)) # tmp3? - tmp4 = self.implement_guard_value(pc, tmp3) # tmp4? - if not tmp4.getint(): - return False - else: - # division overflow! - return self.metainterp.raise_overflow_error() - - @arguments() - def opimpl_overflow_error(self): - return self.metainterp.raise_overflow_error() - - @arguments("orgpc", "box") - def opimpl_int_abs(self, pc, box): - nonneg = self.metainterp.execute_and_record( - rop.INT_GE, None, box, ConstInt(0)) - nonneg = self.implement_guard_value(pc, nonneg) - if nonneg.getint(): - self.make_result_box(box) - else: - self.execute(rop.INT_NEG, box) - - @arguments("orgpc", "box") - def opimpl_oononnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(1) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(0) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("orgpc", "box") - def opimpl_ooisnull(self, pc, box): - value = box.nonnull() - if value: - opnum = rop.GUARD_NONNULL - res = ConstInt(0) - else: - opnum = rop.GUARD_ISNULL - res = ConstInt(1) - self.generate_guard(pc, opnum, box, []) - self.make_result_box(res) - - @arguments("box", "box") - def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, box1, box2) - - @arguments("box", "box") - def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, box1, box2) - - opimpl_oois = opimpl_ptr_eq - opimpl_ooisnot = opimpl_ptr_ne + return indexbox @arguments("box", "descr") - def opimpl_getfield_gc(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC, fielddesc, box) + def _opimpl_getfield_gc_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) + opimpl_getfield_gc_i = _opimpl_getfield_gc_any + opimpl_getfield_gc_r = _opimpl_getfield_gc_any + opimpl_getfield_gc_f = _opimpl_getfield_gc_any + @arguments("box", "descr") - def opimpl_getfield_gc_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddesc, box) + def _opimpl_getfield_gc_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box) + opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any + opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_GC, fielddesc, box, valuebox) + def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) + opimpl_setfield_gc_i = _opimpl_setfield_gc_any + opimpl_setfield_gc_r = _opimpl_setfield_gc_any + opimpl_setfield_gc_f = _opimpl_setfield_gc_any @arguments("box", "descr") - def opimpl_getfield_raw(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW, fielddesc, box) + def _opimpl_getfield_raw_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box) + opimpl_getfield_raw_i = _opimpl_getfield_raw_any + opimpl_getfield_raw_r = _opimpl_getfield_raw_any + opimpl_getfield_raw_f = _opimpl_getfield_raw_any + @arguments("box", "descr") - def opimpl_getfield_raw_pure(self, box, fielddesc): - self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddesc, box) + def _opimpl_getfield_raw_pure_any(self, box, fielddescr): + return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box) + opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any + opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any + @arguments("box", "descr", "box") - def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute_with_descr(rop.SETFIELD_RAW, fielddesc, box, valuebox) + def _opimpl_setfield_raw_any(self, box, fielddescr, valuebox): + self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox) + opimpl_setfield_raw_i = _opimpl_setfield_raw_any + opimpl_setfield_raw_r = _opimpl_setfield_raw_any + opimpl_setfield_raw_f = _opimpl_setfield_raw_any def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable @@ -522,7 +519,7 @@ standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False - eqbox = self.metainterp.execute_and_record(rop.OOIS, None, + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, box, standard_box) eqbox = self.implement_guard_value(pc, eqbox) isstandard = eqbox.getint() @@ -530,9 +527,9 @@ self.metainterp.replace_box(box, standard_box) return not isstandard - def _get_virtualizable_field_descr(self, index): + def _get_virtualizable_field_index(self, fielddescr): vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.static_field_descrs[index] + return vinfo.static_field_by_descrs[fielddescr] def _get_virtualizable_array_field_descr(self, index): vinfo = self.metainterp.staticdata.virtualizable_info @@ -542,328 +539,271 @@ vinfo = self.metainterp.staticdata.virtualizable_info return vinfo.array_descrs[index] - @arguments("orgpc", "box", "int") - def opimpl_getfield_vable(self, pc, basebox, index): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.GETFIELD_GC, self._get_virtualizable_field_descr(index), basebox) - return + @arguments("orgpc", "box", "descr") + def _opimpl_getfield_vable(self, pc, box, fielddescr): + if self._nonstandard_virtualizable(pc, box): + return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box) self.metainterp.check_synchronized_virtualizable() - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box") - def opimpl_setfield_vable(self, pc, basebox, index, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - self.execute_with_descr(rop.SETFIELD_GC, self._get_virtualizable_field_descr(index), basebox, valuebox) + index = self._get_virtualizable_field_index(fielddescr) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getfield_vable_i = _opimpl_getfield_vable + opimpl_getfield_vable_r = _opimpl_getfield_vable + opimpl_getfield_vable_f = _opimpl_getfield_vable + + @arguments("orgpc", "box", "descr", "box") + def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox): + if self._nonstandard_virtualizable(pc, box): + self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox) return + index = self._get_virtualizable_field_index(fielddescr) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - def _get_arrayitem_vable_index(self, pc, arrayindex, indexbox): + opimpl_setfield_vable_i = _opimpl_setfield_vable + opimpl_setfield_vable_r = _opimpl_setfield_vable + opimpl_setfield_vable_f = _opimpl_setfield_vable + + def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): indexbox = self.implement_guard_value(pc, indexbox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] index = indexbox.getint() if index < 0: index += vinfo.get_array_length(virtualizable, arrayindex) assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex) return vinfo.get_index_in_array(virtualizable, arrayindex, index) - @arguments("orgpc", "box", "int", "box") - def opimpl_getarrayitem_vable(self, pc, basebox, arrayindex, indexbox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + @arguments("orgpc", "box", "descr", "descr", "box") + def _opimpl_getarrayitem_vable(self, pc, box, fdescr, adescr, indexbox): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.GETARRAYITEM_GC, descr, - arraybox, indexbox) - return + fdescr, box) + return self.execute_with_descr(rop.GETARRAYITEM_GC, adescr, + arraybox, indexbox) self.metainterp.check_synchronized_virtualizable() - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) - resbox = self.metainterp.virtualizable_boxes[index] - self.make_result_box(resbox) - @arguments("orgpc", "box", "int", "box", "box") - def opimpl_setarrayitem_vable(self, pc, basebox, arrayindex, indexbox, + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) + return self.metainterp.virtualizable_boxes[index] + + opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable + opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr", "box", "box") + def _opimpl_setarrayitem_vable(self, pc, box, fdescr, adescr, indexbox, valuebox): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.SETARRAYITEM_GC, descr, + fdescr, box) + self.execute_with_descr(rop.SETARRAYITEM_GC, adescr, arraybox, indexbox, valuebox) return - index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox) + index = self._get_arrayitem_vable_index(pc, fdescr, indexbox) self.metainterp.virtualizable_boxes[index] = valuebox self.metainterp.synchronize_virtualizable() # XXX only the index'th field needs to be synchronized, really - @arguments("orgpc", "box", "int") - def opimpl_arraylen_vable(self, pc, basebox, arrayindex): - if self._nonstandard_virtualizable(pc, basebox): - descr = self._get_virtualizable_array_field_descr(arrayindex) + + opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable + opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable + + @arguments("orgpc", "box", "descr", "descr") + def opimpl_arraylen_vable(self, pc, box, fdescr, adescr): + if self._nonstandard_virtualizable(pc, box): arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, - descr, basebox) - descr = self._get_virtualizable_array_descr(arrayindex) - self.execute_with_descr(rop.ARRAYLEN_GC, descr, arraybox) - return + fdescr, box) + return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) vinfo = self.metainterp.staticdata.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + arrayindex = vinfo.array_field_by_descrs[fdescr] result = vinfo.get_array_length(virtualizable, arrayindex) - self.make_result_box(ConstInt(result)) + return ConstInt(result) - def perform_call(self, jitcode, varargs, greenkey=None): - if (self.metainterp.is_blackholing() and - jitcode.calldescr is not None): - # when producing only a BlackHole, we can implement this by - # calling the subfunction directly instead of interpreting it - if jitcode.cfnptr is not None: - # for non-oosends - varargs = [jitcode.cfnptr] + varargs - res = self.execute_varargs(rop.CALL, varargs, - descr=jitcode.calldescr, exc=True) - else: - # for oosends (ootype only): calldescr is a MethDescr - res = self.execute_varargs(rop.OOSEND, varargs, - descr=jitcode.calldescr, exc=True) - self.metainterp.load_fields_from_virtualizable() - return res - else: - # when tracing, this bytecode causes the subfunction to be entered - f = self.metainterp.newframe(jitcode, greenkey) - f.setup_call(varargs) - return True - - @arguments("bytecode", "varargs") - def opimpl_call(self, callee, varargs): - return self.perform_call(callee, varargs) - - @arguments("descr", "varargs") - def opimpl_residual_call(self, calldescr, varargs): - return self.do_residual_call(varargs, descr=calldescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_call_loopinvariant(self, calldescr, varargs): - return self.execute_varargs(rop.CALL_LOOPINVARIANT, varargs, calldescr, exc=True) - - @arguments("orgpc", "descr", "varargs") - def opimpl_recursive_call(self, pc, calldescr, varargs): - warmrunnerstate = self.metainterp.staticdata.state + @arguments("jitcode", "boxes") + def _opimpl_inline_call1(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes2") + def _opimpl_inline_call2(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + @arguments("jitcode", "boxes3") + def _opimpl_inline_call3(self, jitcode, argboxes): + return self.metainterp.perform_call(jitcode, argboxes) + + opimpl_inline_call_r_i = _opimpl_inline_call1 + opimpl_inline_call_r_r = _opimpl_inline_call1 + opimpl_inline_call_r_v = _opimpl_inline_call1 + opimpl_inline_call_ir_i = _opimpl_inline_call2 + opimpl_inline_call_ir_r = _opimpl_inline_call2 + opimpl_inline_call_ir_v = _opimpl_inline_call2 + opimpl_inline_call_irf_i = _opimpl_inline_call3 + opimpl_inline_call_irf_r = _opimpl_inline_call3 + opimpl_inline_call_irf_f = _opimpl_inline_call3 + opimpl_inline_call_irf_v = _opimpl_inline_call3 + + @arguments("box", "descr", "boxes") + def _opimpl_residual_call1(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes2") + def _opimpl_residual_call2(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + @arguments("box", "descr", "boxes3") + def _opimpl_residual_call3(self, funcbox, calldescr, argboxes): + return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes) + + opimpl_residual_call_r_i = _opimpl_residual_call1 + opimpl_residual_call_r_r = _opimpl_residual_call1 + opimpl_residual_call_r_v = _opimpl_residual_call1 + opimpl_residual_call_ir_i = _opimpl_residual_call2 + opimpl_residual_call_ir_r = _opimpl_residual_call2 + opimpl_residual_call_ir_v = _opimpl_residual_call2 + opimpl_residual_call_irf_i = _opimpl_residual_call3 + opimpl_residual_call_irf_r = _opimpl_residual_call3 + opimpl_residual_call_irf_f = _opimpl_residual_call3 + opimpl_residual_call_irf_v = _opimpl_residual_call3 + + @arguments("boxes3", "boxes3") + def _opimpl_recursive_call(self, greenboxes, redboxes): + allboxes = greenboxes + redboxes + metainterp_sd = self.metainterp.staticdata + portal_code = metainterp_sd.portal_code + warmrunnerstate = metainterp_sd.state token = None - if not self.metainterp.is_blackholing() and warmrunnerstate.inlining: - num_green_args = self.metainterp.staticdata.num_green_args - portal_code = self.metainterp.staticdata.portal_code - greenkey = varargs[1:num_green_args + 1] - if warmrunnerstate.can_inline_callable(greenkey): - return self.perform_call(portal_code, varargs[1:], greenkey) - token = warmrunnerstate.get_assembler_token(greenkey) - call_position = 0 - if token is not None: - call_position = len(self.metainterp.history.operations) + if warmrunnerstate.inlining: + if warmrunnerstate.can_inline_callable(greenboxes): + return self.metainterp.perform_call(portal_code, allboxes, + greenkey=greenboxes) + token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - greenargs = varargs[1:num_green_args + 1] - self.verify_green_args(greenargs) - res = self.do_residual_call(varargs, descr=calldescr, exc=True) - if not self.metainterp.is_blackholing() and token is not None: - # XXX fix the call position, - found = False - while True: - op = self.metainterp.history.operations[call_position] - if op.opnum == rop.CALL or op.opnum == rop.CALL_MAY_FORCE: - found = True - break - call_position += 1 - assert found - # - # this will substitute the residual call with assembler call - self.metainterp.direct_assembler_call(pc, varargs, token, - call_position) - return res - - @arguments("descr", "varargs") - def opimpl_residual_call_noexception(self, calldescr, varargs): - self.do_residual_call(varargs, descr=calldescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_call_pure(self, calldescr, varargs): - self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False) - - @arguments("orgpc", "descr", "box", "varargs") - def opimpl_indirect_call(self, pc, calldescr, box, varargs): - box = self.implement_guard_value(pc, box) - cpu = self.metainterp.cpu - key = cpu.ts.getaddr_for_box(cpu, box) - jitcode = self.metainterp.staticdata.bytecode_for_address(key) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.do_residual_call([box] + varargs, - descr=calldescr, exc=True) - - @arguments("orgpc", "methdescr", "varargs") - def opimpl_oosend(self, pc, methdescr, varargs): - objbox = varargs[0] - clsbox = self.cls_of_box(objbox) - if isinstance(objbox, Box): - self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) - oocls = clsbox.getref(ootype.Class) - jitcode = methdescr.get_jitcode_for_class(oocls) - if jitcode is not None: - # we should follow calls to this graph - return self.perform_call(jitcode, varargs) - else: - # but we should not follow calls to that graph - return self.execute_varargs(rop.OOSEND, varargs, - descr=methdescr, exc=True) + self.verify_green_args(greenboxes) + # + k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + funcbox = ConstInt(heaptracker.adr2int(k)) + return self.do_residual_call(funcbox, portal_code.calldescr, + allboxes, assembler_call_token=token) + + opimpl_recursive_call_i = _opimpl_recursive_call + opimpl_recursive_call_r = _opimpl_recursive_call + opimpl_recursive_call_f = _opimpl_recursive_call + opimpl_recursive_call_v = _opimpl_recursive_call + +## @FixME #arguments("orgpc", "methdescr", "varargs") +## def opimpl_oosend(self, pc, methdescr, varargs): +## objbox = varargs[0] +## clsbox = self.cls_of_box(objbox) +## if isinstance(objbox, Box): +## self.generate_guard(pc, rop.GUARD_CLASS, objbox, [clsbox]) +## oocls = clsbox.getref(ootype.Class) +## jitcode = methdescr.get_jitcode_for_class(oocls) +## if jitcode is not None: +## # we should follow calls to this graph +## return self.perform_call(jitcode, varargs) +## else: +## # but we should not follow calls to that graph +## return self.execute_varargs(rop.OOSEND, varargs, +## descr=methdescr, exc=True) @arguments("box") - def opimpl_strlen(self, str): - self.execute(rop.STRLEN, str) + def opimpl_strlen(self, strbox): + return self.execute(rop.STRLEN, strbox) @arguments("box") - def opimpl_unicodelen(self, str): - self.execute(rop.UNICODELEN, str) + def opimpl_unicodelen(self, unicodebox): + return self.execute(rop.UNICODELEN, unicodebox) @arguments("box", "box") - def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, str, index) + def opimpl_strgetitem(self, strbox, indexbox): + return self.execute(rop.STRGETITEM, strbox, indexbox) @arguments("box", "box") - def opimpl_unicodegetitem(self, str, index): - self.execute(rop.UNICODEGETITEM, str, index) + def opimpl_unicodegetitem(self, unicodebox, indexbox): + return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox) @arguments("box", "box", "box") - def opimpl_strsetitem(self, str, index, newchar): - self.execute(rop.STRSETITEM, str, index, newchar) + def opimpl_strsetitem(self, strbox, indexbox, newcharbox): + return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox) @arguments("box", "box", "box") - def opimpl_unicodesetitem(self, str, index, newchar): - self.execute(rop.UNICODESETITEM, str, index, newchar) + def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox): + self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox) @arguments("box") - def opimpl_newstr(self, length): - self.execute(rop.NEWSTR, length) + def opimpl_newstr(self, lengthbox): + return self.execute(rop.NEWSTR, lengthbox) @arguments("box") - def opimpl_newunicode(self, length): - self.execute(rop.NEWUNICODE, length) + def opimpl_newunicode(self, lengthbox): + return self.execute(rop.NEWUNICODE, lengthbox) - @arguments("descr", "varargs") - def opimpl_residual_oosend_canraise(self, methdescr, varargs): - return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=True) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_noraise(self, methdescr, varargs): - self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, exc=False) - - @arguments("descr", "varargs") - def opimpl_residual_oosend_pure(self, methdescr, boxes): - self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, exc=False) - - @arguments("orgpc", "box") - def opimpl_guard_value(self, pc, box): - constbox = self.implement_guard_value(pc, box) - self.make_result_box(constbox) - - @arguments("orgpc", "int") - def opimpl_guard_green(self, pc, boxindex): - """Like guard_value, but overwrites the original box with the const. - Used to prevent Boxes from showing up in the greenkey of some - operations, like jit_merge_point. The in-place overwriting is - convenient for jit_merge_point, which expects self.env to contain - not more than the greens+reds described in the jitdriver.""" - box = self.env[boxindex] - constbox = self.implement_guard_value(pc, box) - self.env[boxindex] = constbox +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_canraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=True) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_noraise(self, methdescr, varargs): +## return self.execute_varargs(rop.OOSEND, varargs, descr=methdescr, +## exc=False) + +## @FixME #arguments("descr", "varargs") +## def opimpl_residual_oosend_pure(self, methdescr, boxes): +## return self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, +## exc=False) + + @arguments("orgpc", "box",) + def _opimpl_guard_value(self, orgpc, box): + self.implement_guard_value(orgpc, box) + + opimpl_int_guard_value = _opimpl_guard_value + opimpl_ref_guard_value = _opimpl_guard_value + opimpl_float_guard_value = _opimpl_guard_value @arguments("orgpc", "box") - def opimpl_guard_class(self, pc, box): + def opimpl_guard_class(self, orgpc, box): clsbox = self.cls_of_box(box) - if isinstance(box, Box): - self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) - self.make_result_box(clsbox) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_builtin(self, pc, box, builtin): -## self.generate_guard(pc, "guard_builtin", box, [builtin]) - -## @arguments("orgpc", "box", "builtin") -## def opimpl_guard_len(self, pc, box, builtin): -## intbox = self.metainterp.cpu.execute_operation( -## 'len', [builtin.len_func, box], 'int') -## self.generate_guard(pc, "guard_len", box, [intbox]) - - @arguments("box") - def opimpl_keepalive(self, box): - pass # xxx? - - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args - for i in range(num_green_args): - assert isinstance(varargs[i], Const) - - def blackhole_reached_merge_point(self, varargs): - if self.metainterp.in_recursion: - portal_code = self.metainterp.staticdata.portal_code - # small hack: fish for the result box - lenenv = len(self.env) - raised = self.perform_call(portal_code, varargs) - # in general this cannot be assumed, but when blackholing, - # perform_call returns True only if an exception is called. In - # this case perform_call has called finishframe_exception - # already, so we need to return. - if raised: - return - if lenenv == len(self.env): - res = None - else: - assert lenenv == len(self.env) - 1 - res = self.env.pop() - self.metainterp.finishframe(res) - else: - raise self.metainterp.staticdata.ContinueRunningNormally(varargs) + self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + return clsbox @arguments() def opimpl_can_enter_jit(self): - # Note: when running with a BlackHole history, this 'can_enter_jit' - # may be completely skipped by the logic that replaces perform_call - # with rop.CALL. But in that case, no-one will check the flag anyway, - # so it's fine. if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() self.metainterp.seen_can_enter_jit = True - @arguments() - def opimpl_jit_merge_point(self): - if not self.metainterp.is_blackholing(): - self.verify_green_args(self.env) - # xxx we may disable the following line in some context later - self.debug_merge_point() - if self.metainterp.seen_can_enter_jit: - self.metainterp.seen_can_enter_jit = False - assert not self.metainterp.in_recursion - # ^^^ it's impossible to arrive here with in_recursion set - # to a non-zero value: seen_can_enter_jit can only be set - # to True by opimpl_can_enter_jit, which should be executed - # just before opimpl_jit_merge_point (no recursion inbetween). - try: - self.metainterp.reached_can_enter_jit(self.env) - except GiveUp: - self.metainterp.switch_to_blackhole(ABORT_BRIDGE) - if self.metainterp.is_blackholing(): - self.blackhole_reached_merge_point(self.env) - return True + def verify_green_args(self, varargs): + num_green_args = self.metainterp.staticdata.num_green_args + assert len(varargs) == num_green_args + for i in range(num_green_args): + assert isinstance(varargs[i], Const) + + @arguments("orgpc", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): + self.verify_green_args(greenboxes) + # xxx we may disable the following line in some context later + self.debug_merge_point(greenboxes) + if self.metainterp.seen_can_enter_jit: + self.metainterp.seen_can_enter_jit = False + # Assert that it's impossible to arrive here with in_recursion + # set to a non-zero value: seen_can_enter_jit can only be set + # to True by opimpl_can_enter_jit, which should be executed + # just before opimpl_jit_merge_point (no recursion inbetween). + assert not self.metainterp.in_recursion + # Set self.pc to point to jit_merge_point instead of just after: + # if reached_can_enter_jit() raises SwitchToBlackhole, then the + # pc is still at the jit_merge_point, which is a point that is + # much less expensive to blackhole out of. + saved_pc = self.pc + self.pc = orgpc + self.metainterp.reached_can_enter_jit(greenboxes, redboxes) + self.pc = saved_pc - def debug_merge_point(self): + def debug_merge_point(self, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - num_green_args = self.metainterp.staticdata.num_green_args - greenkey = self.env[:num_green_args] sd = self.metainterp.staticdata loc = sd.state.get_location_str(greenkey) debug_print(loc) @@ -871,45 +811,45 @@ self.metainterp.history.record(rop.DEBUG_MERGE_POINT, [constloc], None) - @arguments("jumptarget") - def opimpl_setup_exception_block(self, exception_target): - self.exception_target = exception_target - - @arguments() - def opimpl_teardown_exception_block(self): - self.exception_target = -1 - - @arguments("constbox", "jumptarget", "orgpc") - def opimpl_goto_if_exception_mismatch(self, vtableref, next_exc_target, pc): - # XXX used to be: - # assert isinstance(self.exception_box, Const) # XXX - # seems this can happen that self.exception_box is not a Const, - # but I failed to write a test so far :-( - self.exception_box = self.implement_guard_value(pc, self.exception_box) - cpu = self.metainterp.cpu - ts = self.metainterp.cpu.ts - if not ts.subclassOf(cpu, self.exception_box, vtableref): + @arguments("box", "label") + def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target): + metainterp = self.metainterp + last_exc_value_box = metainterp.last_exc_value_box + assert last_exc_value_box is not None + assert metainterp.class_of_last_exc_is_const + if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox): self.pc = next_exc_target - @arguments("int") - def opimpl_put_last_exception(self, index): - assert index >= 0 - self.env.insert(index, self.exception_box) - - @arguments("int") - def opimpl_put_last_exc_value(self, index): - assert index >= 0 - self.env.insert(index, self.exc_value_box) + @arguments("orgpc", "box") + def opimpl_raise(self, orgpc, exc_value_box): + # xxx hack + clsbox = self.cls_of_box(exc_value_box) + self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + resumepc=orgpc) + self.metainterp.class_of_last_exc_is_const = True + self.metainterp.last_exc_value_box = exc_value_box + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_raise(self): - assert len(self.env) == 2 - return self.metainterp.finishframe_exception(self.env[0], self.env[1]) + def opimpl_reraise(self): + assert self.metainterp.last_exc_value_box is not None + self.metainterp.popframe() + self.metainterp.finishframe_exception() @arguments() - def opimpl_reraise(self): - return self.metainterp.finishframe_exception(self.exception_box, - self.exc_value_box) + def opimpl_last_exception(self): + # Same comment as in opimpl_goto_if_exception_mismatch(). + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + assert self.metainterp.class_of_last_exc_is_const + return self.metainterp.cpu.ts.cls_of_box(exc_value_box) + + @arguments() + def opimpl_last_exc_value(self): + exc_value_box = self.metainterp.last_exc_value_box + assert exc_value_box is not None + return exc_value_box @arguments("box") def opimpl_virtual_ref(self, box): @@ -920,30 +860,26 @@ # the 'virtual_ref(frame)'). # # * if we detect that the virtual box escapes during tracing - # already (by generating a CALl_MAY_FORCE that marks the flags + # already (by generating a CALL_MAY_FORCE that marks the flags # in the vref), then we replace the vref in the list with # ConstPtr(NULL). # metainterp = self.metainterp - if metainterp.is_blackholing(): - resbox = box # good enough when blackholing - else: - vrefinfo = metainterp.staticdata.virtualref_info - obj = box.getref_base() - vref = vrefinfo.virtual_ref_during_tracing(obj) - resbox = history.BoxPtr(vref) - cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) - metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) - # Note: we allocate a JIT_VIRTUAL_REF here - # (in virtual_ref_during_tracing()), in order to detect when - # the virtual escapes during tracing already. We record it as a - # VIRTUAL_REF operation, although the backend sees this operation - # as a no-op. The point is that the backend should not really see - # it in practice, as optimizeopt.py should either kill it or - # replace it with a NEW_WITH_VTABLE followed by SETFIELD_GCs. + vrefinfo = metainterp.staticdata.virtualref_info + obj = box.getref_base() + vref = vrefinfo.virtual_ref_during_tracing(obj) + resbox = history.BoxPtr(vref) + cindex = history.ConstInt(len(metainterp.virtualref_boxes) // 2) + metainterp.history.record(rop.VIRTUAL_REF, [box, cindex], resbox) + # Note: we allocate a JIT_VIRTUAL_REF here + # (in virtual_ref_during_tracing()), in order to detect when + # the virtual escapes during tracing already. We record it as a + # VIRTUAL_REF operation. Later, optimizeopt.py should either kill + # that operation or replace it with a NEW_WITH_VTABLE followed by + # SETFIELD_GCs. metainterp.virtualref_boxes.append(box) metainterp.virtualref_boxes.append(resbox) - self.make_result_box(resbox) + return resbox @arguments("box") def opimpl_virtual_ref_finish(self, box): @@ -953,27 +889,32 @@ vrefbox = metainterp.virtualref_boxes.pop() lastbox = metainterp.virtualref_boxes.pop() assert box.getref_base() == lastbox.getref_base() - if not metainterp.is_blackholing(): - vrefinfo = metainterp.staticdata.virtualref_info - vref = vrefbox.getref_base() - if vrefinfo.is_virtual_ref(vref): - metainterp.history.record(rop.VIRTUAL_REF_FINISH, - [vrefbox, lastbox], None) + vrefinfo = metainterp.staticdata.virtualref_info + vref = vrefbox.getref_base() + if vrefinfo.is_virtual_ref(vref): + metainterp.history.record(rop.VIRTUAL_REF_FINISH, + [vrefbox, lastbox], None) # ------------------------------ def setup_call(self, argboxes): - if not we_are_translated(): - check_args(*argboxes) self.pc = 0 - self.env = argboxes + count_i = count_r = count_f = 0 + for box in argboxes: + if box.type == history.INT: + self.registers_i[count_i] = box + count_i += 1 + elif box.type == history.REF: + self.registers_r[count_r] = box + count_r += 1 + elif box.type == history.FLOAT: + self.registers_f[count_f] = box + count_f += 1 + else: + raise AssertionError(box.type) - def setup_resume_at_op(self, pc, exception_target, env): - if not we_are_translated(): - check_args(*env) + def setup_resume_at_op(self, pc): self.pc = pc - self.exception_target = exception_target - self.env = env ## values = ' '.join([box.repr_rpython() for box in self.env]) ## log('setup_resume_at_op %s:%d [%s] %d' % (self.jitcode.name, ## self.pc, values, @@ -984,25 +925,21 @@ # whenever the 'opcode_implementations' (which is one of the 'opimpl_' # methods) returns True. This is the case when the current frame # changes, due to a call or a return. - while True: - pc = self.pc - op = ord(self.bytecode[pc]) - #print self.metainterp.opcode_names[op] - self.pc = pc + 1 + try: staticdata = self.metainterp.staticdata - stop = staticdata.opcode_implementations[op](self, pc) - #self.metainterp.most_recent_mp = None - if stop: - break + while True: + pc = self.pc + op = ord(self.bytecode[pc]) + #debug_print(self.jitcode.name, pc) + #print staticdata.opcode_names[op] + staticdata.opcode_implementations[op](self, pc) + except ChangeFrame: + pass - def generate_guard(self, pc, opnum, box, extraargs=[]): + def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): if isinstance(box, Const): # no need for a guard return metainterp = self.metainterp - if metainterp.is_blackholing(): - return - saved_pc = self.pc - self.pc = pc if box is not None: moreargs = [box] + extraargs else: @@ -1020,15 +957,18 @@ virtualizable_boxes = None if metainterp.staticdata.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes + saved_pc = self.pc + if resumepc >= 0: + self.pc = resumepc resume.capture_resumedata(metainterp.framestack, virtualizable_boxes, metainterp.virtualref_boxes, resumedescr) + self.pc = saved_pc self.metainterp.staticdata.profiler.count_ops(opnum, GUARDS) # count metainterp.attach_debug_info(guard_op) - self.pc = saved_pc return guard_op - def implement_guard_value(self, pc, box): + def implement_guard_value(self, orgpc, box): """Promote the given Box into a Const. Note: be careful, it's a bit unclear what occurs if a single opcode needs to generate several ones and/or ones not near the beginning.""" @@ -1036,111 +976,190 @@ return box # no promotion needed, already a Const else: promoted_box = box.constbox() - self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box]) + self.generate_guard(rop.GUARD_VALUE, box, [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, promoted_box) return promoted_box def cls_of_box(self, box): - return self.metainterp.cpu.ts.cls_of_box(self.metainterp.cpu, box) + return self.metainterp.cpu.ts.cls_of_box(box) @specialize.arg(1) def execute(self, opnum, *argboxes): - self.execute_with_descr(opnum, None, *argboxes) + return self.metainterp.execute_and_record(opnum, None, *argboxes) @specialize.arg(1) def execute_with_descr(self, opnum, descr, *argboxes): - resbox = self.metainterp.execute_and_record(opnum, descr, *argboxes) - if resbox is not None: - self.make_result_box(resbox) + return self.metainterp.execute_and_record(opnum, descr, *argboxes) @specialize.arg(1) def execute_varargs(self, opnum, argboxes, descr, exc): + self.metainterp.clear_exception() resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes, descr=descr) - if resbox is not None: - self.make_result_box(resbox) + self.make_result_of_lastop(resbox) + # ^^^ this is done before handle_possible_exception() because we need + # the box to show up in get_list_of_active_boxes() if exc: - return self.metainterp.handle_exception() + self.metainterp.handle_possible_exception() else: - return self.metainterp.assert_no_exception() + self.metainterp.assert_no_exception() + return resbox - def do_residual_call(self, argboxes, descr, exc): + def do_residual_call(self, funcbox, descr, argboxes, + assembler_call_token=None): + # First build allboxes: it may need some reordering from the + # list provided in argboxes, depending on the order in which + # the arguments are expected by the function + allboxes = [None] * (len(argboxes)+1) + allboxes[0] = funcbox + src_i = src_r = src_f = 0 + i = 1 + for kind in descr.get_arg_types(): + if kind == history.INT: + while True: + box = argboxes[src_i] + src_i += 1 + if box.type == history.INT: + break + elif kind == history.REF: + while True: + box = argboxes[src_r] + src_r += 1 + if box.type == history.REF: + break + elif kind == history.FLOAT: + while True: + box = argboxes[src_f] + src_f += 1 + if box.type == history.FLOAT: + break + else: + raise AssertionError + allboxes[i] = box + i += 1 + assert i == len(allboxes) + # effectinfo = descr.get_extra_info() - if effectinfo is None or effectinfo.forces_virtual_or_virtualizable: + if (effectinfo is None or + effectinfo.extraeffect == + effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE or + assembler_call_token is not None): # residual calls require attention to keep virtualizables in-sync + self.metainterp.clear_exception() self.metainterp.vable_and_vrefs_before_residual_call() - # xxx do something about code duplication resbox = self.metainterp.execute_and_record_varargs( - rop.CALL_MAY_FORCE, argboxes, descr=descr) - self.metainterp.vable_and_vrefs_after_residual_call() + rop.CALL_MAY_FORCE, allboxes, descr=descr) + self.metainterp.vrefs_after_residual_call() + if assembler_call_token is not None: + self.metainterp.direct_assembler_call(assembler_call_token) if resbox is not None: - self.make_result_box(resbox) - self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, []) - if exc: - return self.metainterp.handle_exception() + self.make_result_of_lastop(resbox) + self.metainterp.vable_after_residual_call() + self.generate_guard(rop.GUARD_NOT_FORCED, None) + self.metainterp.handle_possible_exception() + return resbox + else: + effect = effectinfo.extraeffect + if effect == effectinfo.EF_CANNOT_RAISE: + return self.execute_varargs(rop.CALL, allboxes, descr, False) + elif effect == effectinfo.EF_PURE: + return self.metainterp.record_result_of_call_pure( + self.execute_varargs(rop.CALL, allboxes, descr, False)) + elif effect == effectinfo.EF_LOOPINVARIANT: + return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes, + descr, True) else: - return self.metainterp.assert_no_exception() + return self.execute_varargs(rop.CALL, allboxes, descr, True) + + def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes): + """The 'residual_call' operation is emitted in two cases: + when we have to generate a residual CALL operation, but also + to handle an indirect_call that may need to be inlined.""" + assert isinstance(funcbox, Const) + sd = self.metainterp.staticdata + key = sd.cpu.ts.getaddr_for_box(funcbox) + jitcode = sd.bytecode_for_address(key) + if jitcode is not None: + # we should follow calls to this graph + return self.metainterp.perform_call(jitcode, argboxes) else: - return self.execute_varargs(rop.CALL, argboxes, descr, exc) + # but we should not follow calls to that graph + return self.do_residual_call(funcbox, calldescr, argboxes) # ____________________________________________________________ class MetaInterpStaticData(object): - virtualizable_info = None logger_noopt = None logger_ops = None - def __init__(self, portal_graph, cpu, stats, options, + def __init__(self, cpu, options, ProfilerClass=EmptyProfiler, warmrunnerdesc=None): self.cpu = cpu - self.stats = stats + self.stats = self.cpu.stats self.options = options self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) - RESULT = portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) - - self.opcode_implementations = [] - self.opcode_names = [] - self.opname_to_index = {} - self.profiler = ProfilerClass() - - self.indirectcall_keys = [] - self.indirectcall_values = [] - self.warmrunnerdesc = warmrunnerdesc - self._op_goto_if_not = self.find_opcode('goto_if_not') - self._op_ooisnull = self.find_opcode('ooisnull') - self._op_oononnull = self.find_opcode('oononnull') backendmodule = self.cpu.__module__ backendmodule = backendmodule.split('.')[-2] self.jit_starting_line = 'JIT starting (%s)' % backendmodule - self.portal_code = None - self._class_sizes = None self._addr2name_keys = [] self._addr2name_values = [] self.__dict__.update(compile.make_done_loop_tokens()) - # store this information for fastpath of call_assembler - d = self.loop_tokens_done_with_this_frame_int[0].finishdescr - self.cpu.done_with_this_frame_int_v = self.cpu.get_fail_descr_number(d) def _freeze_(self): return True - def info_from_codewriter(self, portal_code, class_sizes, - list_of_addr2name, portal_runner_ptr): - self.portal_code = portal_code - self._class_sizes = class_sizes - self._addr2name_keys = [key for key, value in list_of_addr2name] + def setup_insns(self, insns): + self.opcode_names = ['?'] * len(insns) + self.opcode_implementations = [None] * len(insns) + for key, value in insns.items(): + assert self.opcode_implementations[value] is None + self.opcode_names[value] = key + name, argcodes = key.split('/') + opimpl = _get_opimpl_method(name, argcodes) + self.opcode_implementations[value] = opimpl + self.op_catch_exception = insns.get('catch_exception/L', -1) + + def setup_descrs(self, descrs): + self.opcode_descrs = descrs + + def setup_indirectcalltargets(self, indirectcalltargets): + self.indirectcalltargets = list(indirectcalltargets) + + def setup_list_of_addr2name(self, list_of_addr2name): + self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] - self._portal_runner_ptr = portal_runner_ptr - def finish_setup(self, optimizer=None): + def finish_setup(self, codewriter, optimizer=None): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) + # + asm = codewriter.assembler + self.setup_insns(asm.insns) + self.setup_descrs(asm.descrs) + self.setup_indirectcalltargets(asm.indirectcalltargets) + self.setup_list_of_addr2name(asm.list_of_addr2name) + # + self.portal_code = codewriter.mainjitcode + self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.virtualref_info = codewriter.callcontrol.virtualref_info + self.virtualizable_info = codewriter.callcontrol.virtualizable_info + RESULT = codewriter.portal_graph.getreturnvar().concretetype + self.result_type = history.getkind(RESULT) + # + # store this information for fastpath of call_assembler + name = self.result_type + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # warmrunnerdesc = self.warmrunnerdesc if warmrunnerdesc is not None: self.num_green_args = warmrunnerdesc.num_green_args @@ -1156,20 +1175,12 @@ """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: debug_print(self.jit_starting_line) - self._setup_class_sizes() self.cpu.setup_once() if not self.profiler.initialized: self.profiler.start() self.profiler.initialized = True self.globaldata.initialized = True - def _setup_class_sizes(self): - class_sizes = {} - for vtable, sizedescr in self._class_sizes: - vtable = self.cpu.ts.cast_vtable_to_hashable(self.cpu, vtable) - class_sizes[vtable] = sizedescr - self.cpu.set_class_sizes(class_sizes) - def get_name_from_address(self, addr): # for debugging only if we_are_translated(): @@ -1200,39 +1211,16 @@ # because the keys are function addresses, so they # can change from run to run. d = {} - keys = self.indirectcall_keys - values = self.indirectcall_values - for i in range(len(keys)): - d[keys[i]] = values[i] + for jitcode in self.indirectcalltargets: + d[jitcode.fnaddr] = jitcode self.globaldata.indirectcall_dict = d return d.get(fnaddress, None) else: - for i in range(len(self.indirectcall_keys)): - if fnaddress == self.indirectcall_keys[i]: - return self.indirectcall_values[i] + for jitcode in self.indirectcalltargets: + if jitcode.fnaddr == fnaddress: + return jitcode return None - # ---------- construction-time interface ---------- - - def _register_indirect_call_target(self, fnaddress, jitcode): - self.indirectcall_keys.append(fnaddress) - self.indirectcall_values.append(jitcode) - - def find_opcode(self, name): - try: - return self.opname_to_index[name] - except KeyError: - self._register_opcode(name) - return self.opname_to_index[name] - - def _register_opcode(self, opname): - assert len(self.opcode_implementations) < 256, \ - "too many implementations of opcodes!" - name = "opimpl_" + opname - self.opname_to_index[opname] = len(self.opcode_implementations) - self.opcode_names.append(opname) - self.opcode_implementations.append(getattr(MIFrame, name).im_func) - # ---------------- logging ------------------------ def log(self, msg): @@ -1259,6 +1247,7 @@ self.addr2name = None self.loopnumbering = 0 self.resume_virtuals = {} + self.resume_virtuals_not_translated = [] # state = staticdata.state if state is not None: @@ -1283,23 +1272,32 @@ class MetaInterp(object): in_recursion = 0 - _already_allocated_resume_virtuals = None def __init__(self, staticdata): self.staticdata = staticdata self.cpu = staticdata.cpu self.portal_trace_positions = [] + self.free_frames_list = [] + self.last_exc_value_box = None - def is_blackholing(self): - return self.history is None + def perform_call(self, jitcode, boxes, greenkey=None): + # causes the metainterp to enter the given subfunction + # with a special case for recursive portal calls + f = self.newframe(jitcode, greenkey) + f.setup_call(boxes) + raise ChangeFrame def newframe(self, jitcode, greenkey=None): if jitcode is self.staticdata.portal_code: self.in_recursion += 1 - if greenkey is not None and not self.is_blackholing(): + if greenkey is not None: self.portal_trace_positions.append( (greenkey, len(self.history.operations))) - f = MIFrame(self, jitcode, greenkey) + if len(self.free_frames_list) > 0: + f = self.free_frames_list.pop() + else: + f = MIFrame(self) + f.setup(jitcode, greenkey) self.framestack.append(f) return f @@ -1307,23 +1305,27 @@ frame = self.framestack.pop() if frame.jitcode is self.staticdata.portal_code: self.in_recursion -= 1 - if frame.greenkey is not None and not self.is_blackholing(): + if frame.greenkey is not None: self.portal_trace_positions.append( (None, len(self.history.operations))) - return frame + # we save the freed MIFrames to avoid needing to re-create new + # MIFrame objects all the time; they are a bit big, with their + # 3*256 register entries. + frame.cleanup_registers() + self.free_frames_list.append(frame) def finishframe(self, resultbox): - frame = self.popframe() + # handle a non-exceptional return from the current frame + self.last_exc_value_box = None + self.popframe() if self.framestack: - if resultbox is not None: - self.framestack[-1].make_result_box(resultbox) - return True + self.framestack[-1].make_result_of_lastop(resultbox) + raise ChangeFrame else: - if not self.is_blackholing(): - try: - self.compile_done_with_this_frame(resultbox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_done_with_this_frame(resultbox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) sd = self.staticdata if sd.result_type == 'void': assert resultbox is None @@ -1337,30 +1339,25 @@ else: assert False - def finishframe_exception(self, exceptionbox, excvaluebox): - # detect and propagate some exceptions early: - # - AssertionError - # - all subclasses of JitException - if we_are_translated(): - from pypy.jit.metainterp.warmspot import JitException - e = self.cpu.ts.get_exception_obj(excvaluebox) - if isinstance(e, JitException) or isinstance(e, AssertionError): - raise Exception, e - # + def finishframe_exception(self): + excvaluebox = self.last_exc_value_box while self.framestack: frame = self.framestack[-1] - if frame.exception_target >= 0: - frame.pc = frame.exception_target - frame.exception_target = -1 - frame.exception_box = exceptionbox - frame.exc_value_box = excvaluebox - return True + code = frame.bytecode + position = frame.pc # <-- just after the insn that raised + if position < len(code): + opcode = ord(code[position]) + if opcode == self.staticdata.op_catch_exception: + # found a 'catch_exception' instruction; + # jump to the handler + target = ord(code[position+1]) | (ord(code[position+2])<<8) + frame.pc = target + raise ChangeFrame self.popframe() - if not self.is_blackholing(): - try: - self.compile_exit_frame_with_exception(excvaluebox) - except GiveUp: - self.switch_to_blackhole(ABORT_BRIDGE) + try: + self.compile_exit_frame_with_exception(excvaluebox) + except SwitchToBlackhole, stb: + self.aborted_tracing(stb.reason) raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base()) def check_recursion_invariant(self): @@ -1379,19 +1376,7 @@ else: print " ", print jitcode.name - raise Exception - - def raise_overflow_error(self): - etype, evalue = self.cpu.get_overflow_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) - - def raise_zero_division_error(self): - etype, evalue = self.cpu.get_zero_division_error() - return self.finishframe_exception( - self.cpu.ts.get_exception_box(etype), - self.cpu.ts.get_exc_value_box(evalue).constbox()) + raise AssertionError def create_empty_history(self): warmrunnerstate = self.staticdata.state @@ -1412,15 +1397,11 @@ @specialize.arg(1) def execute_and_record(self, opnum, descr, *argboxes): history.check_descr(descr) - assert (opnum != rop.CALL and opnum != rop.CALL_MAY_FORCE - and opnum != rop.OOSEND) + assert not (rop._CANRAISE_FIRST <= opnum <= rop._CANRAISE_LAST) # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - return resbox + resbox = executor.execute(self.cpu, self, opnum, descr, *argboxes) if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: return self._record_helper_pure(opnum, resbox, descr, *argboxes) else: @@ -1433,16 +1414,14 @@ # execute the operation profiler = self.staticdata.profiler profiler.count_ops(opnum) - resbox = executor.execute_varargs(self.cpu, opnum, argboxes, descr) - if self.is_blackholing(): - profiler.count_ops(opnum, BLACKHOLED_OPS) - else: - # check if the operation can be constant-folded away - argboxes = list(argboxes) - if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: - resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) - else: - resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) + resbox = executor.execute_varargs(self.cpu, self, + opnum, argboxes, descr) + # check if the operation can be constant-folded away + argboxes = list(argboxes) + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: + resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes) + else: + resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes) return resbox def _record_helper_pure(self, opnum, resbox, descr, *argboxes): @@ -1478,45 +1457,57 @@ op.pc = self.framestack[-1].pc op.name = self.framestack[-1].jitcode.name - def switch_to_blackhole(self, reason): + def execute_raised(self, exception, constant=False): + if isinstance(exception, JitException): + raise JitException, exception # go through + llexception = get_llexception(self.cpu, exception) + self.execute_ll_raised(llexception, constant) + + def execute_ll_raised(self, llexception, constant=False): + # Exception handling: when execute.do_call() gets an exception it + # calls metainterp.execute_raised(), which puts it into + # 'self.last_exc_value_box'. This is used shortly afterwards + # to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also + # to handle the following opcodes 'goto_if_exception_mismatch'. + llexception = self.cpu.ts.cast_to_ref(llexception) + exc_value_box = self.cpu.ts.get_exc_value_box(llexception) + if constant: + exc_value_box = exc_value_box.constbox() + self.last_exc_value_box = exc_value_box + self.class_of_last_exc_is_const = constant + # 'class_of_last_exc_is_const' means that the class of the value + # stored in the exc_value Box can be assumed to be a Const. This + # is only True after a GUARD_EXCEPTION or GUARD_CLASS. + + def clear_exception(self): + self.last_exc_value_box = None + + def aborted_tracing(self, reason): self.staticdata.profiler.count(reason) debug_print('~~~ ABORTING TRACING') - debug_stop('jit-tracing') - debug_start('jit-blackhole') - self.history = None # start blackholing self.staticdata.stats.aborted() - self.staticdata.profiler.end_tracing() - self.staticdata.profiler.start_blackhole() self.resumekey.reset_counter_from_failure() - switch_to_blackhole._dont_inline_ = True - def switch_to_blackhole_if_trace_too_long(self): - if not self.is_blackholing(): - warmrunnerstate = self.staticdata.state - if len(self.history.operations) > warmrunnerstate.trace_limit: - greenkey_of_huge_function = self.find_biggest_function() - self.portal_trace_positions = None - self.switch_to_blackhole(ABORT_TOO_LONG) - if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state - warmrunnerstate.disable_noninlinable_function( - greenkey_of_huge_function) + def blackhole_if_trace_too_long(self): + warmrunnerstate = self.staticdata.state + if len(self.history.operations) > warmrunnerstate.trace_limit: + greenkey_of_huge_function = self.find_biggest_function() + self.portal_trace_positions = None + if greenkey_of_huge_function is not None: + warmrunnerstate = self.staticdata.state + warmrunnerstate.disable_noninlinable_function( + greenkey_of_huge_function) + raise SwitchToBlackhole(ABORT_TOO_LONG) def _interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, - # a ContinueRunningNormally, or a GenerateMergePoint exception. + # a ExitFrameWithException, or a GenerateMergePoint exception. self.staticdata.stats.entered() - try: - while True: - self.framestack[-1].run_one_step() - self.switch_to_blackhole_if_trace_too_long() - if not we_are_translated(): - self.check_recursion_invariant() - finally: - if self.is_blackholing(): - self.staticdata.profiler.end_blackhole() - else: - self.staticdata.profiler.end_tracing() + while True: + self.framestack[-1].run_one_step() + self.blackhole_if_trace_too_long() + if not we_are_translated(): + self.check_recursion_invariant() def interpret(self): if we_are_translated(): @@ -1527,20 +1518,19 @@ except: import sys if sys.exc_info()[0] is not None: - codewriter.log.info(sys.exc_info()[0].__name__) + self.staticdata.log(sys.exc_info()[0].__name__) raise def compile_and_run_once(self, *args): debug_start('jit-tracing') self.staticdata._setup_once() + self.staticdata.profiler.start_tracing() self.create_empty_history() try: return self._compile_and_run_once(*args) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _compile_and_run_once(self, *args): original_boxes = self.initialize_state_from_start(*args) @@ -1553,20 +1543,22 @@ self.seen_can_enter_jit = False try: self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" def handle_guard_failure(self, key): + debug_start('jit-tracing') + self.staticdata.profiler.start_tracing() assert isinstance(key, compile.ResumeGuardDescr) self.initialize_state_from_guard_failure(key) try: return self._handle_guard_failure(key) finally: - if self.history is None: - debug_stop('jit-blackhole') - else: - debug_stop('jit-tracing') + self.staticdata.profiler.end_tracing() + debug_stop('jit-tracing') def _handle_guard_failure(self, key): original_greenkey = key.original_greenkey @@ -1579,13 +1571,23 @@ try: self.prepare_resume_from_failure(key.guard_opnum) self.interpret() - assert False, "should always raise" except GenerateMergePoint, gmp: return self.designate_target_loop(gmp) + except SwitchToBlackhole, stb: + self.run_blackhole_interp_to_cancel_tracing(stb) + assert False, "should always raise" + + def run_blackhole_interp_to_cancel_tracing(self, stb): + # We got a SwitchToBlackhole exception. Convert the framestack into + # a stack of blackhole interpreters filled with the same values, and + # run it. + from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl + self.aborted_tracing(stb.reason) + convert_and_run_from_pyjitpl(self, stb.raising_exception) + assert False # ^^^ must raise - def remove_consts_and_duplicates(self, boxes, startindex, endindex, - duplicates): - for i in range(startindex, endindex): + def remove_consts_and_duplicates(self, boxes, endindex, duplicates): + for i in range(endindex): box = boxes[i] if isinstance(box, Const) or box in duplicates: oldbox = box @@ -1595,22 +1597,19 @@ else: duplicates[box] = None - def reached_can_enter_jit(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + def reached_can_enter_jit(self, greenboxes, redboxes): duplicates = {} - self.remove_consts_and_duplicates(live_arg_boxes, - num_green_args, - len(live_arg_boxes), + self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) - live_arg_boxes = live_arg_boxes[:] + live_arg_boxes = greenboxes + redboxes if self.staticdata.virtualizable_info is not None: - # we use ':-1' to remove the last item, which is the virtualizable + # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, - 0, len(self.virtualizable_boxes)-1, duplicates) - live_arg_boxes += self.virtualizable_boxes[:-1] + live_arg_boxes += self.virtualizable_boxes + live_arg_boxes.pop() assert len(self.virtualref_boxes) == 0, "missing virtual_ref_finish()?" # Called whenever we reach the 'can_enter_jit' hint. # First, attempt to make a bridge: @@ -1639,11 +1638,12 @@ # Found! Compile it as a loop. if start < 0: # we cannot reconstruct the beginning of the proper loop - raise GiveUp + raise SwitchToBlackhole(ABORT_BRIDGE) # raises in case it works -- which is the common case self.compile(original_boxes, live_arg_boxes, start) # creation of the loop was cancelled! + self.staticdata.log('cancelled, going on...') # Otherwise, no loop found so far, so continue tracing. start = len(self.history.operations) @@ -1658,17 +1658,39 @@ return loop_token def prepare_resume_from_failure(self, opnum): + frame = self.framestack[-1] if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now - self.framestack[-1].follow_jump() + frame.pc = frame.jitcode.follow_jump(frame.pc) elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping - self.framestack[-1].dont_follow_jump() - elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION - or opnum == rop.GUARD_NOT_FORCED): - self.handle_exception() + pass + elif opnum == rop.GUARD_VALUE or opnum == rop.GUARD_CLASS: + pass # the pc is already set to the *start* of the opcode + elif (opnum == rop.GUARD_NONNULL or + opnum == rop.GUARD_ISNULL or + opnum == rop.GUARD_NONNULL_CLASS): + pass # the pc is already set to the *start* of the opcode + elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION: + exception = self.cpu.grab_exc_value() + if exception: + self.execute_ll_raised(lltype.cast_opaque_ptr(rclass.OBJECTPTR, + exception)) + else: + self.clear_exception() + try: + self.handle_possible_exception() + except ChangeFrame: + pass elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected - self.raise_overflow_error() - elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL: - self.framestack[-1].ignore_next_guard_nullness(opnum) + self.execute_raised(OverflowError(), constant=True) + try: + self.finishframe_exception() + except ChangeFrame: + pass + elif opnum == rop.GUARD_OVERFLOW: # no longer overflowing + self.clear_exception() + else: + from pypy.jit.metainterp.resoperation import opname + raise NotImplementedError(opname[opnum]) def compile(self, original_boxes, live_arg_boxes, start): num_green_args = self.staticdata.num_green_args @@ -1720,7 +1742,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def compile_exit_frame_with_exception(self, valuebox): self.gen_store_back_in_virtualizable() @@ -1731,7 +1753,7 @@ target_loop_token = compile.compile_new_bridge(self, loop_tokens, self.resumekey) if target_loop_token is not loop_tokens[0]: - raise GiveUp + compile.giveup() def get_residual_args(self, specnodes, args): if specnodes is None: # it is None only for tests @@ -1753,15 +1775,13 @@ def initialize_state_from_start(self, *args): self.in_recursion = -1 # always one portal around - self.staticdata.profiler.start_tracing() num_green_args = self.staticdata.num_green_args original_boxes = [] self._initialize_from_start(original_boxes, num_green_args, *args) # ----- make a new frame ----- self.framestack = [] f = self.newframe(self.staticdata.portal_code) - f.pc = 0 - f.env = original_boxes[:] + f.setup_call(original_boxes) self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) return original_boxes @@ -1769,20 +1789,9 @@ def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack self.in_recursion = -1 # always one portal around - inputargs_and_holes = self.cpu.make_boxes_from_latest_values( - resumedescr) - must_compile = resumedescr.must_compile(self.staticdata, - inputargs_and_holes) - if must_compile: - debug_start('jit-tracing') - self.history = history.History() - self.history.inputargs = [box for box in inputargs_and_holes if box] - self.staticdata.profiler.start_tracing() - else: - debug_start('jit-blackhole') - self.staticdata.profiler.start_blackhole() - self.history = None # this means that is_blackholing() is true - self.rebuild_state_after_failure(resumedescr, inputargs_and_holes) + self.history = history.History() + inputargs_and_holes = self.rebuild_state_after_failure(resumedescr) + self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): vinfo = self.staticdata.virtualizable_info @@ -1804,9 +1813,6 @@ vinfo.clear_vable_token(virtualizable) def vable_and_vrefs_before_residual_call(self): - if self.is_blackholing(): - return - # vrefinfo = self.staticdata.virtualref_info for i in range(1, len(self.virtualref_boxes), 2): vrefbox = self.virtualref_boxes[i] @@ -1827,37 +1833,31 @@ force_token_box], None, descr=vinfo.vable_token_descr) - def vable_and_vrefs_after_residual_call(self): - if self.is_blackholing(): - escapes = True - else: - escapes = False - # - vrefinfo = self.staticdata.virtualref_info - for i in range(0, len(self.virtualref_boxes), 2): - virtualbox = self.virtualref_boxes[i] - vrefbox = self.virtualref_boxes[i+1] - vref = vrefbox.getref_base() - if vrefinfo.tracing_after_residual_call(vref): - # this vref was really a virtual_ref, but it escaped - # during this CALL_MAY_FORCE. Mark this fact by - # generating a VIRTUAL_REF_FINISH on it and replacing - # it by ConstPtr(NULL). - self.stop_tracking_virtualref(i) - # - vinfo = self.staticdata.virtualizable_info - if vinfo is not None: - virtualizable_box = self.virtualizable_boxes[-1] - virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) - if vinfo.tracing_after_residual_call(virtualizable): - # the virtualizable escaped during CALL_MAY_FORCE. - escapes = True - # - if escapes: - self.switch_to_blackhole(ABORT_ESCAPE) - # - if escapes: - self.load_fields_from_virtualizable() + def vrefs_after_residual_call(self): + vrefinfo = self.staticdata.virtualref_info + for i in range(0, len(self.virtualref_boxes), 2): + virtualbox = self.virtualref_boxes[i] + vrefbox = self.virtualref_boxes[i+1] + vref = vrefbox.getref_base() + if vrefinfo.tracing_after_residual_call(vref): + # this vref was really a virtual_ref, but it escaped + # during this CALL_MAY_FORCE. Mark this fact by + # generating a VIRTUAL_REF_FINISH on it and replacing + # it by ConstPtr(NULL). + self.stop_tracking_virtualref(i) + + def vable_after_residual_call(self): + vinfo = self.staticdata.virtualizable_info + if vinfo is not None: + virtualizable_box = self.virtualizable_boxes[-1] + virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) + if vinfo.tracing_after_residual_call(virtualizable): + # the virtualizable escaped during CALL_MAY_FORCE. + self.load_fields_from_virtualizable() + raise SwitchToBlackhole(ABORT_ESCAPE, raising_exception=True) + # ^^^ we set 'raising_exception' to True because we must still + # have the eventual exception raised (this is normally done + # after the call to vable_after_residual_call()). def stop_tracking_virtualref(self, i): virtualbox = self.virtualref_boxes[i] @@ -1871,44 +1871,37 @@ # mark by replacing it with ConstPtr(NULL) self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL - def handle_exception(self): - etype = self.cpu.get_exception() - evalue = self.cpu.get_exc_value() - assert bool(etype) == bool(evalue) - self.cpu.clear_exception() + def handle_possible_exception(self): frame = self.framestack[-1] - if etype: - exception_box = self.cpu.ts.get_exception_box(etype) - exc_value_box = self.cpu.ts.get_exc_value_box(evalue) - op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION, + if self.last_exc_value_box is not None: + exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box) + op = frame.generate_guard(rop.GUARD_EXCEPTION, None, [exception_box]) - if op: - op.result = exc_value_box - return self.finishframe_exception(exception_box, exc_value_box) + assert op is not None + op.result = self.last_exc_value_box + self.class_of_last_exc_is_const = True + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) - return False - - def assert_no_exception(self): - assert not self.cpu.get_exception() - return False + frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) - def handle_overflow_error(self): + def handle_possible_overflow_error(self): frame = self.framestack[-1] - if self.cpu._overflow_flag: - self.cpu._overflow_flag = False - frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None, []) - return self.raise_overflow_error() + if self.last_exc_value_box is not None: + frame.generate_guard(rop.GUARD_OVERFLOW, None) + assert isinstance(self.last_exc_value_box, Const) + assert self.class_of_last_exc_is_const + self.finishframe_exception() else: - frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None, []) - return False + frame.generate_guard(rop.GUARD_NO_OVERFLOW, None) + + def assert_no_exception(self): + assert self.last_exc_value_box is None - def rebuild_state_after_failure(self, resumedescr, newboxes): + def rebuild_state_after_failure(self, resumedescr): vinfo = self.staticdata.virtualizable_info self.framestack = [] - expect_virtualizable = vinfo is not None - virtualizable_boxes, virtualref_boxes = resume.rebuild_from_resumedata( - self, newboxes, resumedescr, expect_virtualizable) + boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) + inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists # # virtual refs: make the vrefs point to the freshly allocated virtuals self.virtualref_boxes = virtualref_boxes @@ -1921,7 +1914,7 @@ # # virtualizable: synchronize the real virtualizable and the local # boxes, in whichever direction is appropriate - if expect_virtualizable: + if vinfo is not None: self.virtualizable_boxes = virtualizable_boxes # just jumped away from assembler (case 4 in the comment in # virtualizable.py) into tracing (case 2); check that vable_token @@ -1930,13 +1923,14 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if self._already_allocated_resume_virtuals is not None: + if 0: ## self._already_allocated_resume_virtuals is not None: # resuming from a ResumeGuardForcedDescr: load the new values # currently stored on the virtualizable fields self.load_fields_from_virtualizable() else: # normal case: fill the virtualizable with the local boxes self.synchronize_virtualizable() + return inputargs_and_holes def check_synchronized_virtualizable(self): if not we_are_translated(): @@ -1953,8 +1947,8 @@ def load_fields_from_virtualizable(self): # Force a reload of the virtualizable fields into the local - # boxes (called only in escaping cases) - assert self.is_blackholing() + # boxes (called only in escaping cases). Only call this function + # just before SwitchToBlackhole. vinfo = self.staticdata.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] @@ -2003,11 +1997,9 @@ return boxes def replace_box(self, oldbox, newbox): + assert isinstance(oldbox, Box) for frame in self.framestack: - boxes = frame.env - for i in range(len(boxes)): - if boxes[i] is oldbox: - boxes[i] = newbox + frame.replace_active_box_in_frame(oldbox, newbox) boxes = self.virtualref_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2019,8 +2011,6 @@ boxes[i] = newbox def find_biggest_function(self): - assert not self.is_blackholing() - start_stack = [] max_size = 0 max_key = None @@ -2042,23 +2032,178 @@ max_key = key return max_key - def direct_assembler_call(self, pc, varargs, token, call_position): - """ Generate a direct call to assembler for portal entry point. + def record_result_of_call_pure(self, resbox): + """ Patch a CALL into a CALL_PURE. + """ + op = self.history.operations[-1] + assert op.opnum == rop.CALL + resbox_as_const = resbox.constbox() + for arg in op.args: + if not isinstance(arg, Const): + break + else: + # all-constants: remove the CALL operation now and propagate a + # constant result + self.history.operations.pop() + return resbox_as_const + # not all constants (so far): turn CALL into CALL_PURE, which might + # be either removed later by optimizeopt or turned back into CALL. + op.opnum = rop.CALL_PURE + op.args = [resbox_as_const] + op.args + return resbox + + def direct_assembler_call(self, token): + """ Generate a direct call to assembler for portal entry point, + patching the CALL_MAY_FORCE that occurred just now. """ - assert not self.is_blackholing() # XXX + op = self.history.operations.pop() + assert op.opnum == rop.CALL_MAY_FORCE num_green_args = self.staticdata.num_green_args - args = varargs[num_green_args + 1:] - resbox = self.history.operations[call_position].result - rest = self.history.slice_history_at(call_position) + args = op.args[num_green_args + 1:] if self.staticdata.virtualizable_info is not None: vindex = self.staticdata.virtualizable_info.index_of_virtualizable vbox = args[vindex - num_green_args] - args += self.gen_load_from_other_virtualizable(vbox) - self.history.record(rop.CALL_ASSEMBLER, args[:], resbox, descr=token) - self.history.operations += rest + args = args + self.gen_load_from_other_virtualizable(vbox) + # ^^^ and not "+=", which makes 'args' a resizable list + op.opnum = rop.CALL_ASSEMBLER + op.args = args + op.descr = token + self.history.operations.append(op) -class GenerateMergePoint(Exception): +# ____________________________________________________________ + +class GenerateMergePoint(JitException): def __init__(self, args, target_loop_token): assert target_loop_token is not None self.argboxes = args self.target_loop_token = target_loop_token + +class ChangeFrame(JitException): + """Raised after we mutated metainterp.framestack, in order to force + it to reload the current top-of-stack frame that gets interpreted.""" + +class SwitchToBlackhole(JitException): + def __init__(self, reason, raising_exception=False): + self.reason = reason + self.raising_exception = raising_exception + # ^^^ must be set to True if the SwitchToBlackhole is raised at a + # point where the exception on metainterp.last_exc_value_box + # is supposed to be raised. The default False means that it + # should just be copied into the blackhole interp, but not raised. + +# ____________________________________________________________ + +def _get_opimpl_method(name, argcodes): + from pypy.jit.metainterp.blackhole import signedord + # + def handler(self, position): + assert position >= 0 + args = () + next_argcode = 0 + code = self.bytecode + orgpc = position + position += 1 + for argtype in argtypes: + if argtype == "box": # a box, of whatever type + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = self.registers_i[ord(code[position])] + elif argcode == 'c': + value = ConstInt(signedord(code[position])) + elif argcode == 'r': + value = self.registers_r[ord(code[position])] + elif argcode == 'f': + value = self.registers_f[ord(code[position])] + else: + raise AssertionError("bad argcode") + position += 1 + elif argtype == "descr" or argtype == "jitcode": + assert argcodes[next_argcode] == 'd' + next_argcode = next_argcode + 1 + index = ord(code[position]) | (ord(code[position+1])<<8) + value = self.metainterp.staticdata.opcode_descrs[index] + if argtype == "jitcode": + assert isinstance(value, JitCode) + position += 2 + elif argtype == "label": + assert argcodes[next_argcode] == 'L' + next_argcode = next_argcode + 1 + value = ord(code[position]) | (ord(code[position+1])<<8) + position += 2 + elif argtype == "boxes": # a list of boxes of some type + length = ord(code[position]) + value = [None] * length + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + next_argcode = next_argcode + 1 + position += 1 + length + elif argtype == "boxes2": # two lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + value = [None] * (length1 + length2) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + next_argcode = next_argcode + 2 + position = position2 + 1 + length2 + elif argtype == "boxes3": # three lists of boxes merged into one + length1 = ord(code[position]) + position2 = position + 1 + length1 + length2 = ord(code[position2]) + position3 = position2 + 1 + length2 + length3 = ord(code[position3]) + value = [None] * (length1 + length2 + length3) + self.prepare_list_of_boxes(value, 0, position, + argcodes[next_argcode]) + self.prepare_list_of_boxes(value, length1, position2, + argcodes[next_argcode + 1]) + self.prepare_list_of_boxes(value, length1 + length2, position3, + argcodes[next_argcode + 2]) + next_argcode = next_argcode + 3 + position = position3 + 1 + length3 + elif argtype == "orgpc": + value = orgpc + else: + raise AssertionError("bad argtype: %r" % (argtype,)) + args += (value,) + # + num_return_args = len(argcodes) - next_argcode + assert num_return_args == 0 or num_return_args == 2 + if num_return_args: + # Save the type of the resulting box. This is needed if there is + # a get_list_of_active_boxes(). See comments there. + self._result_argcode = argcodes[next_argcode + 1] + position += 1 + else: + self._result_argcode = 'v' + self.pc = position + # + if not we_are_translated(): + print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))), + try: + resultbox = unboundmethod(self, *args) + except Exception, e: + print '-> %s!' % e.__class__.__name__ + raise + if num_return_args == 0: + print + assert resultbox is None + else: + print '-> %r' % (resultbox,) + assert argcodes[next_argcode] == '>' + result_argcode = argcodes[next_argcode + 1] + assert resultbox.type == {'i': history.INT, + 'r': history.REF, + 'f': history.FLOAT}[result_argcode] + else: + resultbox = unboundmethod(self, *args) + # + self.make_result_of_lastop(resultbox) + # + unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func + argtypes = unrolling_iterable(unboundmethod.argtypes) + handler.func_name = 'handler_' + name + return handler Modified: pypy/branch/fast-forward/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/resoperation.py Sun Jun 20 18:38:42 2010 @@ -22,10 +22,11 @@ self.setdescr(descr) def setdescr(self, descr): - # for 'call', 'new', 'getfield_gc'...: the descr is a number provided - # by the backend holding details about the type of the operation -- - # actually an instance of a class, typically Descr, that inherits - # from AbstractDescr + # for 'call', 'new', 'getfield_gc'...: the descr is a prebuilt + # instance provided by the backend holding details about the type + # of the operation. It must inherit from AbstractDescr. The + # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(), + # cpu.calldescrof(), and cpu.typedescrof(). from pypy.jit.metainterp.history import check_descr check_descr(descr) self.descr = descr @@ -134,10 +135,6 @@ '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations ----- '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations ----- - 'OOSEND_PURE', # ootype operation - 'CALL_PURE', - # - 'CAST_PTR_TO_INT/1', 'INT_ADD/2', 'INT_SUB/2', 'INT_MUL/2', @@ -156,7 +153,6 @@ 'FLOAT_TRUEDIV/2', 'FLOAT_NEG/1', 'FLOAT_ABS/1', - 'FLOAT_IS_TRUE/1b', 'CAST_FLOAT_TO_INT/1', 'CAST_INT_TO_FLOAT/1', # @@ -177,15 +173,15 @@ 'FLOAT_GT/2b', 'FLOAT_GE/2b', # + 'INT_IS_ZERO/1b', 'INT_IS_TRUE/1b', 'INT_NEG/1', 'INT_INVERT/1', - 'BOOL_NOT/1b', # 'SAME_AS/1', # gets a Const or a Box, turns it into another Box # - 'OOIS/2b', - 'OOISNOT/2b', + 'PTR_EQ/2b', + 'PTR_NE/2b', # 'ARRAYLEN_GC/1d', 'STRLEN/1', @@ -197,8 +193,8 @@ 'UNICODEGETITEM/2', # # ootype operations - 'INSTANCEOF/1db', - 'SUBCLASSOF/2b', + #'INSTANCEOF/1db', + #'SUBCLASSOF/2b', # '_ALWAYS_PURE_LAST', # ----- end of always_pure operations ----- @@ -209,29 +205,32 @@ 'NEW_WITH_VTABLE/1', 'NEW_ARRAY/1d', 'FORCE_TOKEN/0', - 'VIRTUAL_REF/2', + 'VIRTUAL_REF/2', # removed before it's passed to the backend '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations ----- 'SETARRAYITEM_GC/3d', 'SETARRAYITEM_RAW/3d',#only added by backend.llsupport.gc.rewrite_assembler 'SETFIELD_GC/2d', 'SETFIELD_RAW/2d', - 'ARRAYCOPY/7d', + 'ARRAYCOPY/7d', # removed before it's passed to the backend 'NEWSTR/1', 'STRSETITEM/3', 'UNICODESETITEM/3', 'NEWUNICODE/1', - 'RUNTIMENEW/1', # ootype operation + #'RUNTIMENEW/1', # ootype operation 'COND_CALL_GC_WB', # [objptr, newvalue] (for the write barrier) 'DEBUG_MERGE_POINT/1', # debugging only - 'VIRTUAL_REF_FINISH/2', + 'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend '_CANRAISE_FIRST', # ----- start of can_raise operations ----- 'CALL', 'CALL_ASSEMBLER', 'CALL_MAY_FORCE', 'CALL_LOOPINVARIANT', - 'OOSEND', # ootype operation + #'OOSEND', # ootype operation + #'OOSEND_PURE', # ootype operation + 'CALL_PURE', # removed before it's passed to the backend + # CALL_PURE(result, func, arg_1,..,arg_n) '_CANRAISE_LAST', # ----- end of can_raise operations ----- '_OVF_FIRST', # ----- start of is_ovf operations ----- Modified: pypy/branch/fast-forward/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/resume.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/resume.py Sun Jun 20 18:38:42 2010 @@ -1,10 +1,12 @@ import sys, os -from pypy.jit.metainterp.history import Box, Const, ConstInt, INT, REF +from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind +from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat +from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import jitprof -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rlib import rarithmetic -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.rlib.debug import have_debug_prints from pypy.rlib.debug import debug_start, debug_stop, debug_print @@ -21,26 +23,29 @@ self.boxes = boxes class FrameInfo(object): - __slots__ = ('prev', 'jitcode', 'pc', 'exception_target') + __slots__ = ('prev', 'jitcode', 'pc') - def __init__(self, prev, frame): + def __init__(self, prev, jitcode, pc): self.prev = prev - self.jitcode = frame.jitcode - self.pc = frame.pc - self.exception_target = frame.exception_target + self.jitcode = jitcode + self.pc = pc def _ensure_parent_resumedata(framestack, n): target = framestack[n] - if n == 0 or target.parent_resumedata_frame_info_list is not None: + if n == 0: return - _ensure_parent_resumedata(framestack, n-1) back = framestack[n-1] + if target.parent_resumedata_frame_info_list is not None: + assert target.parent_resumedata_frame_info_list.pc == back.pc + return + _ensure_parent_resumedata(framestack, n-1) target.parent_resumedata_frame_info_list = FrameInfo( back.parent_resumedata_frame_info_list, - back) + back.jitcode, + back.pc) target.parent_resumedata_snapshot = Snapshot( back.parent_resumedata_snapshot, - back.env[:]) + back.get_list_of_active_boxes(True)) def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, storage): @@ -48,12 +53,15 @@ top = framestack[n] _ensure_parent_resumedata(framestack, n) frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, - top) + top.jitcode, top.pc) storage.rd_frame_info_list = frame_info_list - snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:]) - snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now + snapshot = Snapshot(top.parent_resumedata_snapshot, + top.get_list_of_active_boxes(False)) if virtualizable_boxes is not None: - snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now + boxes = virtualref_boxes + virtualizable_boxes + else: + boxes = virtualref_boxes[:] + snapshot = Snapshot(snapshot, boxes) storage.rd_snapshot = snapshot class Numbering(object): @@ -182,6 +190,7 @@ n += 1 liveboxes[box] = tagged nums[i] = tagged + # numb = Numbering(numb1, nums) self.numberings[snapshot] = numb, liveboxes, v return numb, liveboxes.copy(), v @@ -388,10 +397,10 @@ class AbstractVirtualInfo(object): - def allocate(self, metainterp): - raise NotImplementedError - def setfields(self, metainterp, box, fn_decode_box): - raise NotImplementedError + #def allocate(self, metainterp): + # raise NotImplementedError + #def setfields(self, decoder, struct): + # raise NotImplementedError def equals(self, fieldnums): return tagged_list_eq(self.fieldnums, fieldnums) def set_content(self, fieldnums): @@ -405,12 +414,11 @@ self.fielddescrs = fielddescrs #self.fieldnums = ... - def setfields(self, metainterp, box, fn_decode_box): + @specialize.argtype(1) + def setfields(self, decoder, struct): for i in range(len(self.fielddescrs)): - fieldbox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETFIELD_GC, - self.fielddescrs[i], - box, fieldbox) + descr = self.fielddescrs[i] + decoder.setfield(descr, struct, self.fieldnums[i]) def debug_prints(self): assert len(self.fielddescrs) == len(self.fieldnums) @@ -424,9 +432,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.known_class = known_class - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - None, self.known_class) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_with_vtable(self.known_class) def debug_prints(self): debug_print("\tvirtualinfo", self.known_class.repr_rpython()) @@ -437,8 +445,9 @@ AbstractVirtualStructInfo.__init__(self, fielddescrs) self.typedescr = typedescr - def allocate(self, metainterp): - return metainterp.execute_and_record(rop.NEW, self.typedescr) + @specialize.argtype(1) + def allocate(self, decoder): + return decoder.allocate_struct(self.typedescr) def debug_prints(self): debug_print("\tvstructinfo", self.typedescr.repr_rpython()) @@ -449,117 +458,457 @@ self.arraydescr = arraydescr #self.fieldnums = ... - def allocate(self, metainterp): + @specialize.argtype(1) + def allocate(self, decoder): length = len(self.fieldnums) - return metainterp.execute_and_record(rop.NEW_ARRAY, - self.arraydescr, - ConstInt(length)) - - def setfields(self, metainterp, box, fn_decode_box): - for i in range(len(self.fieldnums)): - itembox = fn_decode_box(self.fieldnums[i]) - metainterp.execute_and_record(rop.SETARRAYITEM_GC, - self.arraydescr, - box, ConstInt(i), itembox) + return decoder.allocate_array(self.arraydescr, length) + + @specialize.argtype(1) + def setfields(self, decoder, array): + arraydescr = self.arraydescr + length = len(self.fieldnums) + # NB. the check for the kind of array elements is moved out of the loop + if arraydescr.is_array_of_pointers(): + for i in range(length): + decoder.setarrayitem_ref(arraydescr, array, i, + self.fieldnums[i]) + elif arraydescr.is_array_of_floats(): + for i in range(length): + decoder.setarrayitem_float(arraydescr, array, i, + self.fieldnums[i]) + else: + for i in range(length): + decoder.setarrayitem_int(arraydescr, array, i, + self.fieldnums[i]) def debug_prints(self): debug_print("\tvarrayinfo", self.arraydescr) for i in self.fieldnums: debug_print("\t\t", str(untag(i))) +# ____________________________________________________________ -def rebuild_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - frameinfo = storage.rd_frame_info_list - while True: - env = resumereader.consume_boxes() - f = metainterp.newframe(frameinfo.jitcode) - f.setup_resume_at_op(frameinfo.pc, frameinfo.exception_target, env) - frameinfo = frameinfo.prev - if frameinfo is None: - break - metainterp.framestack.reverse() - return virtualizable_boxes, virtualref_boxes - -def force_from_resumedata(metainterp, newboxes, storage, - expects_virtualizables): - resumereader = ResumeDataReader(storage, newboxes, metainterp) - virtualizable_boxes = None - if expects_virtualizables: - virtualizable_boxes = resumereader.consume_boxes() - virtualref_boxes = resumereader.consume_boxes() - return virtualizable_boxes, virtualref_boxes, resumereader.virtuals - - -class ResumeDataReader(object): +class AbstractResumeDataReader(object): + """A base mixin containing the logic to reconstruct virtuals out of + guard failure. There are two implementations of this mixin: + ResumeDataBoxReader for when we are compiling (i.e. when we have a + metainterp), and ResumeDataDirectReader for when we are merely + blackholing and want the best performance. + """ + _mixin_ = True virtuals = None + virtual_default = None - def __init__(self, storage, liveboxes, metainterp=None): + def _init(self, cpu, storage): + self.cpu = cpu self.cur_numb = storage.rd_numb self.consts = storage.rd_consts - self.liveboxes = liveboxes - self.cpu = metainterp.cpu - self._prepare_virtuals(metainterp, storage.rd_virtuals) - self._prepare_pendingfields(metainterp, storage.rd_pendingfields) - def _prepare_virtuals(self, metainterp, virtuals): + def _prepare(self, storage): + self._prepare_virtuals(storage.rd_virtuals) + self._prepare_pendingfields(storage.rd_pendingfields) + + def _prepare_virtuals(self, virtuals): if virtuals: - v = metainterp._already_allocated_resume_virtuals - if v is not None: - self.virtuals = v - return - self.virtuals = [None] * len(virtuals) + self.virtuals = [self.virtual_default] * len(virtuals) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - self.virtuals[i] = vinfo.allocate(metainterp) + self.virtuals[i] = vinfo.allocate(self) for i in range(len(virtuals)): vinfo = virtuals[i] if vinfo is not None: - vinfo.setfields(metainterp, self.virtuals[i], - self._decode_box) + vinfo.setfields(self, self.virtuals[i]) - def _prepare_pendingfields(self, metainterp, pendingfields): - if pendingfields: - if metainterp._already_allocated_resume_virtuals is not None: - return + def _prepare_pendingfields(self, pendingfields): + if pendingfields is not None: for descr, num, fieldnum in pendingfields: - box = self._decode_box(num) - fieldbox = self._decode_box(fieldnum) - metainterp.execute_and_record(rop.SETFIELD_GC, - descr, box, fieldbox) - - def consume_boxes(self): - numb = self.cur_numb - assert numb is not None - nums = numb.nums - n = len(nums) - boxes = [None] * n - for i in range(n): - boxes[i] = self._decode_box(nums[i]) - self.cur_numb = numb.prev - return boxes + struct = self.decode_ref(num) + self.setfield(descr, struct, fieldnum) + + def _prepare_next_section(self, info): + # Use info.enumerate_vars(), normally dispatching to + # pypy.jit.codewriter.jitcode. Some tests give a different 'info'. + info.enumerate_vars(self._callback_i, + self._callback_r, + self._callback_f, + self.unique_id) # <-- annotation hack + self.cur_numb = self.cur_numb.prev + + def _callback_i(self, index, register_index): + value = self.decode_int(self.cur_numb.nums[index]) + self.write_an_int(register_index, value) + + def _callback_r(self, index, register_index): + value = self.decode_ref(self.cur_numb.nums[index]) + self.write_a_ref(register_index, value) + + def _callback_f(self, index, register_index): + value = self.decode_float(self.cur_numb.nums[index]) + self.write_a_float(register_index, value) + + def done(self): + self.cpu.clear_latest_values(self.cpu.get_latest_value_count()) + +# ---------- when resuming for pyjitpl.py, make boxes ---------- + +def rebuild_from_resumedata(metainterp, storage, virtualizable_info): + resumereader = ResumeDataBoxReader(storage, metainterp) + boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info) + virtualizable_boxes, virtualref_boxes = boxes + frameinfo = storage.rd_frame_info_list + while True: + f = metainterp.newframe(frameinfo.jitcode) + f.setup_resume_at_op(frameinfo.pc) + resumereader.consume_boxes(f.get_current_position_info(), + f.registers_i, f.registers_r, f.registers_f) + frameinfo = frameinfo.prev + if frameinfo is None: + break + metainterp.framestack.reverse() + resumereader.done() + return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes + +class ResumeDataBoxReader(AbstractResumeDataReader): + unique_id = lambda: None - def _decode_box(self, tagged): + def __init__(self, storage, metainterp): + self._init(metainterp.cpu, storage) + self.metainterp = metainterp + self.liveboxes = [None] * metainterp.cpu.get_latest_value_count() + self._prepare(storage) + + def consume_boxes(self, info, boxes_i, boxes_r, boxes_f): + self.boxes_i = boxes_i + self.boxes_r = boxes_r + self.boxes_f = boxes_f + self._prepare_next_section(info) + + def consume_virtualizable_boxes(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], and use it to know how many + # boxes of which type we have to return. This does not write + # anything into the virtualizable. + virtualizablebox = self.decode_ref(nums[-1]) + virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox) + return vinfo.load_list_of_boxes(virtualizable, self, nums) + + def consume_virtualref_boxes(self, nums, end): + # Returns a list of boxes, assumed to be all BoxPtrs. + # We leave up to the caller to call vrefinfo.continue_tracing(). + assert (end & 1) == 0 + return [self.decode_ref(nums[i]) for i in range(end)] + + def consume_vref_and_vable_boxes(self, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if vinfo is None: + virtualizable_boxes = None + end = len(nums) + else: + virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums) + end = len(nums) - len(virtualizable_boxes) + virtualref_boxes = self.consume_virtualref_boxes(nums, end) + return virtualizable_boxes, virtualref_boxes + + def allocate_with_vtable(self, known_class): + return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE, + None, known_class) + + def allocate_struct(self, typedescr): + return self.metainterp.execute_and_record(rop.NEW, typedescr) + + def allocate_array(self, arraydescr, length): + return self.metainterp.execute_and_record(rop.NEW_ARRAY, + arraydescr, ConstInt(length)) + + def setfield(self, descr, structbox, fieldnum): + if descr.is_pointer_field(): + kind = REF + elif descr.is_float_field(): + kind = FLOAT + else: + kind = INT + fieldbox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETFIELD_GC, descr, + structbox, fieldbox) + + def setarrayitem_int(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, INT) + + def setarrayitem_ref(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, REF) + + def setarrayitem_float(self, arraydescr, arraybox, index, fieldnum): + self.setarrayitem(arraydescr, arraybox, index, fieldnum, FLOAT) + + def setarrayitem(self, arraydescr, arraybox, index, fieldnum, kind): + itembox = self.decode_box(fieldnum, kind) + self.metainterp.execute_and_record(rop.SETARRAYITEM_GC, + arraydescr, arraybox, + ConstInt(index), itembox) + + def decode_int(self, tagged): + return self.decode_box(tagged, INT) + def decode_ref(self, tagged): + return self.decode_box(tagged, REF) + def decode_float(self, tagged): + return self.decode_box(tagged, FLOAT) + + def decode_box(self, tagged, kind): num, tag = untag(tagged) if tag == TAGCONST: if tagged_eq(tagged, NULLREF): - return self.cpu.ts.CONST_NULL - return self.consts[num] + box = self.cpu.ts.CONST_NULL + else: + box = self.consts[num] elif tag == TAGVIRTUAL: virtuals = self.virtuals assert virtuals is not None - return virtuals[num] + box = virtuals[num] + elif tag == TAGINT: + box = ConstInt(num) + else: + assert tag == TAGBOX + box = self.liveboxes[num] + if box is None: + box = self.load_box_from_cpu(num, kind) + assert box.type == kind + return box + + def load_box_from_cpu(self, num, kind): + if num < 0: + num += len(self.liveboxes) + assert num >= 0 + if kind == INT: + box = BoxInt(self.cpu.get_latest_value_int(num)) + elif kind == REF: + box = BoxPtr(self.cpu.get_latest_value_ref(num)) + elif kind == FLOAT: + box = BoxFloat(self.cpu.get_latest_value_float(num)) + else: + assert 0, "bad kind: %d" % ord(kind) + self.liveboxes[num] = box + return box + + def decode_box_of_type(self, TYPE, tagged): + kind = getkind(TYPE) + if kind == 'int': kind = INT + elif kind == 'ref': kind = REF + elif kind == 'float': kind = FLOAT + else: raise AssertionError(kind) + return self.decode_box(tagged, kind) + decode_box_of_type._annspecialcase_ = 'specialize:arg(1)' + + def write_an_int(self, index, box): + self.boxes_i[index] = box + def write_a_ref(self, index, box): + self.boxes_r[index] = box + def write_a_float(self, index, box): + self.boxes_f[index] = box + +# ---------- when resuming for blackholing, get direct values ---------- + +def blackhole_from_resumedata(blackholeinterpbuilder, storage, + all_virtuals=None): + resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, + all_virtuals) + vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + # + # First get a chain of blackhole interpreters whose length is given + # by the depth of rd_frame_info_list. The first one we get must be + # the bottom one, i.e. the last one in the chain, in order to make + # the comment in BlackholeInterpreter.setposition() valid. + nextbh = None + frameinfo = storage.rd_frame_info_list + while True: + curbh = blackholeinterpbuilder.acquire_interp() + curbh.nextblackholeinterp = nextbh + nextbh = curbh + frameinfo = frameinfo.prev + if frameinfo is None: + break + firstbh = nextbh + # + # Now fill the blackhole interpreters with resume data. + curbh = firstbh + frameinfo = storage.rd_frame_info_list + while True: + curbh.setposition(frameinfo.jitcode, frameinfo.pc) + resumereader.consume_one_section(curbh) + curbh = curbh.nextblackholeinterp + frameinfo = frameinfo.prev + if frameinfo is None: + break + resumereader.done() + return firstbh + +def force_from_resumedata(metainterp_sd, storage): + resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) + resumereader.handling_async_forcing() + vinfo = metainterp_sd.virtualizable_info + vrefinfo = metainterp_sd.virtualref_info + resumereader.consume_vref_and_vable(vrefinfo, vinfo) + return resumereader.virtuals + +class ResumeDataDirectReader(AbstractResumeDataReader): + unique_id = lambda: None + virtual_default = lltype.nullptr(llmemory.GCREF.TO) + resume_after_guard_not_forced = 0 + # 0: not a GUARD_NOT_FORCED + # 1: in handle_async_forcing + # 2: resuming from the GUARD_NOT_FORCED + + def __init__(self, cpu, storage, all_virtuals=None): + self._init(cpu, storage) + if all_virtuals is None: # common case + self._prepare(storage) + else: + # special case for resuming after a GUARD_NOT_FORCED: we already + # have the virtuals + self.resume_after_guard_not_forced = 2 + self.virtuals = all_virtuals + + def handling_async_forcing(self): + self.resume_after_guard_not_forced = 1 + + def consume_one_section(self, blackholeinterp): + self.blackholeinterp = blackholeinterp + info = blackholeinterp.get_current_position_info() + self._prepare_next_section(info) + + def consume_virtualref_info(self, vrefinfo, nums, end): + # we have to decode a list of references containing pairs + # [..., virtual, vref, ...] stopping at 'end' + assert (end & 1) == 0 + for i in range(0, end, 2): + virtual = self.decode_ref(nums[i]) + vref = self.decode_ref(nums[i+1]) + # For each pair, we store the virtual inside the vref. + vrefinfo.continue_tracing(vref, virtual) + + def consume_vable_info(self, vinfo, nums): + # we have to ignore the initial part of 'nums' (containing vrefs), + # find the virtualizable from nums[-1], load all other values + # from the CPU stack, and copy them into the virtualizable + if vinfo is None: + return len(nums) + virtualizable = self.decode_ref(nums[-1]) + virtualizable = vinfo.cast_gcref_to_vtype(virtualizable) + if self.resume_after_guard_not_forced == 1: + # in the middle of handle_async_forcing() + assert virtualizable.vable_token + virtualizable.vable_token = vinfo.TOKEN_NONE + else: + # just jumped away from assembler (case 4 in the comment in + # virtualizable.py) into tracing (case 2); check that vable_token + # is and stays 0. Note the call to reset_vable_token() in + # warmstate.py. + assert not virtualizable.vable_token + return vinfo.write_from_resume_data_partial(virtualizable, self, nums) + + def load_value_of_type(self, TYPE, tagged): + from pypy.jit.metainterp.warmstate import specialize_value + kind = getkind(TYPE) + if kind == 'int': + x = self.decode_int(tagged) + elif kind == 'ref': + x = self.decode_ref(tagged) + elif kind == 'float': + x = self.decode_float(tagged) + else: + raise AssertionError(kind) + return specialize_value(TYPE, x) + load_value_of_type._annspecialcase_ = 'specialize:arg(1)' + + def consume_vref_and_vable(self, vrefinfo, vinfo): + nums = self.cur_numb.nums + self.cur_numb = self.cur_numb.prev + if self.resume_after_guard_not_forced != 2: + end_vref = self.consume_vable_info(vinfo, nums) + self.consume_virtualref_info(vrefinfo, nums, end_vref) + + def allocate_with_vtable(self, known_class): + from pypy.jit.metainterp.executor import exec_new_with_vtable + return exec_new_with_vtable(self.cpu, known_class) + + def allocate_struct(self, typedescr): + return self.cpu.bh_new(typedescr) + + def allocate_array(self, arraydescr, length): + return self.cpu.bh_new_array(arraydescr, length) + + def setfield(self, descr, struct, fieldnum): + if descr.is_pointer_field(): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setfield_gc_r(struct, descr, newvalue) + elif descr.is_float_field(): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setfield_gc_f(struct, descr, newvalue) + else: + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setfield_gc_i(struct, descr, newvalue) + + def setarrayitem_int(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_int(fieldnum) + self.cpu.bh_setarrayitem_gc_i(arraydescr, array, index, newvalue) + + def setarrayitem_ref(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_ref(fieldnum) + self.cpu.bh_setarrayitem_gc_r(arraydescr, array, index, newvalue) + + def setarrayitem_float(self, arraydescr, array, index, fieldnum): + newvalue = self.decode_float(fieldnum) + self.cpu.bh_setarrayitem_gc_f(arraydescr, array, index, newvalue) + + def decode_int(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getint() elif tag == TAGINT: - return ConstInt(num) + return num else: assert tag == TAGBOX - return self.liveboxes[num] + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_int(num) + + def decode_ref(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + if tagged_eq(tagged, NULLREF): + return self.cpu.ts.NULLREF + return self.consts[num].getref_base() + elif tag == TAGVIRTUAL: + virtuals = self.virtuals + assert virtuals is not None + return virtuals[num] + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_ref(num) + + def decode_float(self, tagged): + num, tag = untag(tagged) + if tag == TAGCONST: + return self.consts[num].getfloat() + else: + assert tag == TAGBOX + if num < 0: + num += self.cpu.get_latest_value_count() + return self.cpu.get_latest_value_float(num) + + def write_an_int(self, index, int): + self.blackholeinterp.setarg_i(index, int) + + def write_a_ref(self, index, ref): + self.blackholeinterp.setarg_r(index, ref) + + def write_a_float(self, index, float): + self.blackholeinterp.setarg_f(index, float) # ____________________________________________________________ @@ -576,7 +925,7 @@ except AttributeError: jitcodename = str(compute_unique_id(frameinfo.jitcode)) debug_print('\tjitcode/pc', jitcodename, - frameinfo.pc, frameinfo.exception_target, + frameinfo.pc, 'at', compute_unique_id(frameinfo)) frameinfo = frameinfo.prev numb = storage.rd_numb Modified: pypy/branch/fast-forward/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/simple_optimize.py Sun Jun 20 18:38:42 2010 @@ -10,12 +10,18 @@ def transform(op): from pypy.jit.metainterp.history import AbstractDescr # change ARRAYCOPY to call, so we don't have to pass around - # unnecessary information to the backend + # unnecessary information to the backend. Do the same with VIRTUAL_REF_*. if op.opnum == rop.ARRAYCOPY: descr = op.args[0] assert isinstance(descr, AbstractDescr) - return ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) - return op + op = ResOperation(rop.CALL, op.args[1:], op.result, descr=descr) + elif op.opnum == rop.CALL_PURE: + op = ResOperation(rop.CALL, op.args[1:], op.result, op.descr) + elif op.opnum == rop.VIRTUAL_REF: + op = ResOperation(rop.SAME_AS, [op.args[0]], op.result) + elif op.opnum == rop.VIRTUAL_REF_FINISH: + return [] + return [op] def optimize_loop(metainterp_sd, old_loops, loop): if old_loops: @@ -35,7 +41,7 @@ modifier = resume.ResumeDataVirtualAdder(descr, memo) newboxes = modifier.finish(EMPTY_VALUES) descr.store_final_boxes(op, newboxes) - newoperations.append(transform(op)) + newoperations.extend(transform(op)) loop.operations = newoperations return None Modified: pypy/branch/fast-forward/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/specnode.py Sun Jun 20 18:38:42 2010 @@ -57,7 +57,8 @@ from pypy.jit.metainterp import executor, history, resoperation for ofs, subspecnode in self.fields: assert isinstance(ofs, history.AbstractDescr) - fieldbox = executor.execute(cpu, resoperation.rop.GETFIELD_GC, + fieldbox = executor.execute(cpu, None, + resoperation.rop.GETFIELD_GC, ofs, valuebox) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -95,7 +96,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp import executor, history, resoperation for i in range(len(self.items)): - itembox = executor.execute(cpu, resoperation.rop.GETARRAYITEM_GC, + itembox = executor.execute(cpu, None, + resoperation.rop.GETARRAYITEM_GC, self.arraydescr, valuebox, history.ConstInt(i)) subspecnode = self.items[i] Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/oparser.py Sun Jun 20 18:38:42 2010 @@ -4,10 +4,11 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\ - ConstAddr, ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ + ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\ LoopToken from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.typesystem import llhelper +from pypy.jit.codewriter.heaptracker import adr2int from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llstr @@ -74,8 +75,7 @@ return ConstPtr(obj) else: assert typ == 'class' - return ConstAddr(llmemory.cast_ptr_to_adr(obj), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(obj))) else: if typ == 'ptr': return ConstObj(obj) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py Sun Jun 20 18:38:42 2010 @@ -4,30 +4,97 @@ from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp import support, codewriter, pyjitpl, history -from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy +from pypy.jit.metainterp import pyjitpl, history +from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy from pypy import conftest from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype -def _get_bare_metainterp(func, values, CPUClass, type_system, - listops=False): - from pypy.annotation.policy import AnnotatorPolicy - from pypy.annotation.model import lltype_to_annotation - from pypy.rpython.test.test_llinterp import gengraph +def _get_jitcodes(testself, CPUClass, func, values, type_system): + from pypy.jit.codewriter import support, codewriter + from pypy.jit.metainterp import simple_optimize - rtyper = support.annotate(func, values, type_system=type_system) + class FakeWarmRunnerState: + def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): + pass + + # pick the optimizer this way + optimize_loop = staticmethod(simple_optimize.optimize_loop) + optimize_bridge = staticmethod(simple_optimize.optimize_bridge) + trace_limit = sys.maxint + debug_level = 2 + + func._jit_unroll_safe_ = True + rtyper = support.annotate(func, values, type_system=type_system) + graphs = rtyper.annotator.translator.graphs stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - graphs = rtyper.annotator.translator.graphs - opt = history.Options(listops=listops) - metainterp_sd = pyjitpl.MetaInterpStaticData(graphs[0], cpu, stats, opt) - metainterp_sd.finish_setup(optimizer="bogus") + cw = codewriter.CodeWriter(cpu, graphs[0]) + testself.cw = cw + cw.find_all_graphs(JitPolicy()) + # + testself.warmrunnerstate = FakeWarmRunnerState() + testself.warmrunnerstate.cpu = cpu + if hasattr(testself, 'finish_setup_for_interp_operations'): + testself.finish_setup_for_interp_operations() + # + cw.make_jitcodes(verbose=True) + +def _run_with_blackhole(testself, args): + from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder + cw = testself.cw + blackholeinterpbuilder = BlackholeInterpBuilder(cw) + blackholeinterp = blackholeinterpbuilder.acquire_interp() + count_i = count_r = count_f = 0 + for value in args: + T = lltype.typeOf(value) + if T == lltype.Signed: + blackholeinterp.setarg_i(count_i, value) + count_i += 1 + elif T == llmemory.GCREF: + blackholeinterp.setarg_r(count_r, value) + count_r += 1 + elif T == lltype.Float: + blackholeinterp.setarg_f(count_f, value) + count_f += 1 + else: + raise TypeError(T) + blackholeinterp.setposition(cw.mainjitcode, 0) + blackholeinterp.run() + return blackholeinterp._final_result_anytype() + +def _run_with_pyjitpl(testself, args): + + class DoneWithThisFrame(Exception): + pass + + class DoneWithThisFrameRef(DoneWithThisFrame): + def __init__(self, cpu, *args): + DoneWithThisFrame.__init__(self, *args) + + cw = testself.cw + opt = history.Options(listops=True) + metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) + metainterp_sd.finish_setup(cw, optimizer="bogus") + metainterp_sd.state = testself.warmrunnerstate + metainterp_sd.state.cpu = metainterp_sd.cpu metainterp = pyjitpl.MetaInterp(metainterp_sd) - return metainterp, rtyper + metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame + metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef + metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame + testself.metainterp = metainterp + try: + metainterp.compile_and_run_once(*args) + except DoneWithThisFrame, e: + #if conftest.option.view: + # metainterp.stats.view() + return e.args[0] + else: + raise Exception("FAILED") + class JitMixin: basic = True @@ -63,56 +130,14 @@ return ll_meta_interp(*args, **kwds) def interp_operations(self, f, args, **kwds): - from pypy.jit.metainterp import simple_optimize - - class DoneWithThisFrame(Exception): - pass - - class DoneWithThisFrameRef(DoneWithThisFrame): - def __init__(self, cpu, *args): - DoneWithThisFrame.__init__(self, *args) - - class FakeWarmRunnerState: - def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): - pass - - # pick the optimizer this way - optimize_loop = staticmethod(simple_optimize.optimize_loop) - optimize_bridge = staticmethod(simple_optimize.optimize_bridge) - - trace_limit = sys.maxint - debug_level = 2 - - metainterp, rtyper = _get_bare_metainterp(f, args, self.CPUClass, - self.type_system, - **kwds) - metainterp.staticdata.state = FakeWarmRunnerState() - metainterp.staticdata.state.cpu = metainterp.staticdata.cpu - if hasattr(self, 'finish_metainterp_for_interp_operations'): - self.finish_metainterp_for_interp_operations(metainterp) - portal_graph = rtyper.annotator.translator.graphs[0] - cw = codewriter.CodeWriter(rtyper) - - graphs = cw.find_all_graphs(portal_graph, JitPolicy(), - self.CPUClass.supports_floats) - cw._start(metainterp.staticdata, None) - portal_graph.func._jit_unroll_safe_ = True - maingraph = cw.make_one_bytecode((portal_graph, None), False) - cw.finish_making_bytecodes() - metainterp.staticdata.portal_code = maingraph - metainterp.staticdata._class_sizes = cw.class_sizes - metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame - metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef - metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame - self.metainterp = metainterp - try: - metainterp.compile_and_run_once(*args) - except DoneWithThisFrame, e: - #if conftest.option.view: - # metainterp.stats.view() - return e.args[0] - else: - raise Exception("FAILED") + # get the JitCodes for the function f + _get_jitcodes(self, self.CPUClass, f, args, self.type_system) + # try to run it with blackhole.py + result1 = _run_with_blackhole(self, args) + # try to run it with pyjitpl.py + result2 = _run_with_pyjitpl(self, args) + assert result1 == result2 + return result1 def check_history(self, expected=None, **isns): # this can be used after calling meta_interp @@ -120,6 +145,9 @@ def check_operations_history(self, expected=None, **isns): # this can be used after interp_operations + if expected is not None: + expected = dict(expected) + expected['jump'] = 1 self.metainterp.staticdata.stats.check_history(expected, **isns) @@ -151,7 +179,7 @@ class OOJitMixin(JitMixin): type_system = 'ootype' - CPUClass = runner.OOtypeCPU + #CPUClass = runner.OOtypeCPU def setup_class(cls): py.test.skip("ootype tests skipped for now") @@ -204,10 +232,12 @@ from pypy.rlib.rarithmetic import r_uint def f(a, b): + a = r_uint(a) + b = r_uint(b) return a/b - res = self.interp_operations(f, [r_uint(4), r_uint(3)]) - assert res == 1 + res = self.interp_operations(f, [-4, 3]) + assert res == long(r_uint(-4)) // 3 def test_direct_call(self): def g(n): @@ -337,7 +367,74 @@ return externfn(n, n+1) res = self.interp_operations(f, [6]) assert res == 42 - self.check_operations_history(int_add=0, int_mul=0, call=0) + # CALL_PURE is not recorded in the history if all-constant args + self.check_operations_history(int_add=0, int_mul=0, + call=0, call_pure=0) + + def test_residual_call_pure_1(self): + def externfn(x, y): + return x * y + externfn._pure_function_ = True + def f(n): + return externfn(n, n+1) + res = self.interp_operations(f, [6]) + assert res == 42 + # CALL_PURE is recorded in the history if not-all-constant args + self.check_operations_history(int_add=1, int_mul=0, + call=0, call_pure=1) + + def test_residual_call_pure_2(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + def externfn(x): + return x - 1 + externfn._pure_function_ = True + def f(n): + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + n = externfn(n) + return n + res = self.meta_interp(f, [7]) + assert res == 0 + # CALL_PURE is recorded in the history, but turned into a CALL + # by optimizeopt.py + self.check_loops(int_sub=0, call=1, call_pure=0) + + def test_constfold_call_pure(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + n -= externfn(m) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) + + def test_constfold_call_pure_2(self): + myjitdriver = JitDriver(greens = ['m'], reds = ['n']) + def externfn(x): + return x - 3 + externfn._pure_function_ = True + class V: + def __init__(self, value): + self.value = value + def f(n, m): + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + v = V(m) + n -= externfn(v.value) + return n + res = self.meta_interp(f, [21, 5]) + assert res == -1 + # the CALL_PURE is constant-folded away by optimizeopt.py + self.check_loops(int_sub=1, call=0, call_pure=0) def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) @@ -444,6 +541,76 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_uint_operations(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + return ((r_uint(n) - 123) >> 1) <= r_uint(456) + res = self.interp_operations(f, [50]) + assert res == False + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + + def test_uint_condition(self): + from pypy.rlib.rarithmetic import r_uint + def f(n): + if ((r_uint(n) - 123) >> 1) <= r_uint(456): + return 24 + else: + return 12 + res = self.interp_operations(f, [50]) + assert res == 12 + self.check_operations_history(int_rshift=0, uint_rshift=1, + int_le=0, uint_le=1, + int_sub=1) + + def test_int_between(self): + # + def check(arg1, arg2, arg3, expect_result, **expect_operations): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop + loc = locals().copy() + exec py.code.Source(""" + def f(n, m, p): + arg1 = %(arg1)s + arg2 = %(arg2)s + arg3 = %(arg3)s + return llop.int_between(lltype.Bool, arg1, arg2, arg3) + """ % locals()).compile() in loc + res = self.interp_operations(loc['f'], [5, 6, 7]) + assert res == expect_result + self.check_operations_history(expect_operations) + # + check('n', 'm', 'p', True, int_sub=2, uint_lt=1) + check('n', 'p', 'm', False, int_sub=2, uint_lt=1) + # + check('n', 'm', 6, False, int_sub=2, uint_lt=1) + # + check('n', 4, 'p', False, int_sub=2, uint_lt=1) + check('n', 5, 'p', True, int_sub=2, uint_lt=1) + check('n', 8, 'p', False, int_sub=2, uint_lt=1) + # + check('n', 6, 7, True, int_sub=2, uint_lt=1) + # + check(-2, 'n', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'm', 'p', True, int_sub=2, uint_lt=1) + check(-2, 'p', 'm', False, int_sub=2, uint_lt=1) + #check(0, 'n', 'p', True, uint_lt=1) xxx implement me + #check(0, 'm', 'p', True, uint_lt=1) + #check(0, 'p', 'm', False, uint_lt=1) + # + check(2, 'n', 6, True, int_sub=1, uint_lt=1) + check(2, 'm', 6, False, int_sub=1, uint_lt=1) + check(2, 'p', 6, False, int_sub=1, uint_lt=1) + check(5, 'n', 6, True, int_eq=1) # 6 == 5+1 + check(5, 'm', 6, False, int_eq=1) # 6 == 5+1 + # + check(2, 6, 'm', False, int_sub=1, uint_lt=1) + check(2, 6, 'p', True, int_sub=1, uint_lt=1) + # + check(2, 40, 6, False) + check(2, 40, 60, True) + def test_getfield(self): class A: pass @@ -513,6 +680,39 @@ res = self.interp_operations(f, [15]) assert res == -1 + def test_int_add_ovf(self): + def f(x, y): + try: + return ovfcheck(x + y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -98 + res = self.interp_operations(f, [1, sys.maxint]) + assert res == -42 + + def test_int_sub_ovf(self): + def f(x, y): + try: + return ovfcheck(x - y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -102 + res = self.interp_operations(f, [1, -sys.maxint]) + assert res == -42 + + def test_int_mul_ovf(self): + def f(x, y): + try: + return ovfcheck(x * y) + except OverflowError: + return -42 + res = self.interp_operations(f, [-100, 2]) + assert res == -200 + res = self.interp_operations(f, [-3, sys.maxint//2]) + assert res == -42 + def test_mod_ovf(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) def f(n, x, y): @@ -523,6 +723,7 @@ return n res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + self.check_loops(call=0) def test_abs(self): myjitdriver = JitDriver(greens = [], reds = ['i', 't']) @@ -581,10 +782,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) def test_bridge_from_interpreter_2(self): # one case for backend - computing of framesize on guard failure @@ -731,21 +931,26 @@ def test_zerodivisionerror(self): # test the case of exception-raising operation that is not delegated # to the backend at all: ZeroDivisionError - from pypy.rpython.lltypesystem.lloperation import llop # def f(n): + assert n >= 0 try: - return llop.int_mod_ovf_zer(lltype.Signed, 5, n) + return ovfcheck(5 % n) except ZeroDivisionError: return -666 + except OverflowError: + return -777 res = self.interp_operations(f, [0]) assert res == -666 # def f(n): + assert n >= 0 try: - return llop.int_floordiv_ovf_zer(lltype.Signed, 6, n) + return ovfcheck(6 // n) except ZeroDivisionError: return -667 + except OverflowError: + return -778 res = self.interp_operations(f, [0]) assert res == -667 @@ -795,7 +1000,7 @@ assert not res def test_isinstance_2(self): - driver = JitDriver(greens = [], reds = ['x', 'n', 'sum']) + driver = JitDriver(greens = [], reds = ['n', 'sum', 'x']) class A: pass class B(A): @@ -836,7 +1041,9 @@ return obj.a res = self.interp_operations(fn, [1]) assert res == 1 - self.check_operations_history(guard_class=0, instanceof=0) + self.check_operations_history(guard_class=0) + if self.type_system == 'ootype': + self.check_operations_history(instanceof=0) def test_r_dict(self): from pypy.rlib.objectmodel import r_dict @@ -1017,10 +1224,10 @@ def test_residual_external_call(self): import math - myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res']) def f(x, y): x = float(x) - res = 0 + res = 0.0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) @@ -1259,7 +1466,7 @@ self.check_loops(call=1) def test_bug_optimizeopt_mutates_ops(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'a', 'const']) + myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a']) class A(object): pass class B(A): @@ -1326,6 +1533,16 @@ # this checks that the logic triggered by make_a_counter_per_value() # works and prevents generating tons of bridges + def test_swap_values(self): + def f(x, y): + if x > 5: + x, y = y, x + return x - y + res = self.interp_operations(f, [10, 2]) + assert res == -8 + res = self.interp_operations(f, [3, 2]) + assert res == 1 + class TestOOtype(BasicTests, OOJitMixin): @@ -1426,33 +1643,47 @@ from pypy.rpython.lltypesystem import lltype TP = lltype.Struct('x') - def f(p1, p2): + def f(i1, i2): + p1 = prebuilt[i1] + p2 = prebuilt[i2] a = p1 is p2 b = p1 is not p2 c = bool(p1) d = not bool(p2) return 1000*a + 100*b + 10*c + d - x = lltype.malloc(TP, flavor='raw') - expected = f(x, x) - assert self.interp_operations(f, [x, x]) == expected - lltype.free(x, flavor='raw') + prebuilt = [lltype.malloc(TP, flavor='raw')] * 2 + expected = f(0, 1) + assert self.interp_operations(f, [0, 1]) == expected def test_casts(self): + py.test.skip("xxx fix or kill") if not self.basic: py.test.skip("test written in a style that " "means it's frontend only") - from pypy.rpython.lltypesystem import lltype, llmemory - - TP = lltype.GcStruct('x') + from pypy.rpython.lltypesystem import lltype, llmemory, rffi + + TP = lltype.GcStruct('S1') def f(p): n = lltype.cast_ptr_to_int(p) return n - x = lltype.malloc(TP) - res = self.interp_operations(f, [x]) - expected = self.metainterp.cpu.do_cast_ptr_to_int( - history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))).value - assert res == expected + xref = lltype.cast_opaque_ptr(llmemory.GCREF, x) + res = self.interp_operations(f, [xref]) + y = llmemory.cast_ptr_to_adr(x) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) + # + TP = lltype.Struct('S2') + prebuilt = [lltype.malloc(TP, immortal=True), + lltype.malloc(TP, immortal=True)] + def f(x): + p = prebuilt[x] + n = lltype.cast_ptr_to_int(p) + return n + res = self.interp_operations(f, [1]) + y = llmemory.cast_ptr_to_adr(prebuilt[1]) + y = llmemory.cast_adr_to_int(y) + assert rffi.get_real_int(res) == rffi.get_real_int(y) def test_collapsing_ptr_eq(self): S = lltype.GcStruct('S') Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_blackhole.py Sun Jun 20 18:38:42 2010 @@ -1,87 +1,211 @@ +import py from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp import pyjitpl +from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder +from pypy.jit.metainterp.blackhole import BlackholeInterpreter +from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl +from pypy.jit.metainterp import history, pyjitpl +from pypy.jit.codewriter.assembler import JitCode +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.llinterp import LLException -class BlackholeTests(object): - - def meta_interp(self, *args): - def counting_init(frame, metainterp, jitcode, greenkey=None): - previnit(frame, metainterp, jitcode, greenkey) - self.seen_frames.append(jitcode.name) +class FakeCodeWriter: + pass +class FakeAssembler: + pass +class FakeCPU: + def bh_call_i(self, func, calldescr, args_i, args_r, args_f): + assert func == 321 + assert calldescr == "" + if args_i[0] < 0: + raise LLException("etype", "evalue") + return args_i[0] * 2 + +def getblackholeinterp(insns, descrs=[]): + cw = FakeCodeWriter() + cw.cpu = FakeCPU() + cw.assembler = FakeAssembler() + cw.assembler.insns = insns + cw.assembler.descrs = descrs + builder = BlackholeInterpBuilder(cw) + return builder.acquire_interp() + +def test_simple(): + jitcode = JitCode("test") + jitcode.setup("\x00\x00\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_add/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0, 40) + blackholeinterp.setarg_i(1, 2) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_const(): + jitcode = JitCode("test") + jitcode.setup("\x00\x30\x01\x02" + "\x01\x02", + []) + blackholeinterp = getblackholeinterp({'int_sub/ci>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 6) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_bigconst(): + jitcode = JitCode("test") + jitcode.setup("\x00\xFD\x01\x02" + "\x01\x02", + [666, 666, 10042, 666]) + blackholeinterp = getblackholeinterp({'int_sub/ii>i': 0, + 'int_return/i': 1}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(1, 10000) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_simple_loop(): + jitcode = JitCode("test") + jitcode.setup("\x00\x16\x02\x10\x00" # L1: goto_if_not_int_gt %i0, 2, L2 + "\x01\x17\x16\x17" # int_add %i1, %i0, %i1 + "\x02\x16\x01\x16" # int_sub %i0, $1, %i0 + "\x03\x00\x00" # goto L1 + "\x04\x17", # L2: int_return %i1 + []) + blackholeinterp = getblackholeinterp({'goto_if_not_int_gt/icL': 0, + 'int_add/ii>i': 1, + 'int_sub/ic>i': 2, + 'goto/L': 3, + 'int_return/i': 4}) + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x16, 6) # %i0 + blackholeinterp.setarg_i(0x17, 100) # %i1 + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 100+6+5+4+3 + +def test_simple_exception(): + jitcode = JitCode("test") + jitcode.setup( # residual_call_ir_i $<* fn g>, , I[%i9], R[], %i8 + "\x01\xFF\x00\x00\x01\x09\x00\x08" + "\x00\x0D\x00" # catch_exception L1 + "\x02\x08" # int_return %i8 + "\x03\x2A", # L1: int_return $42 + [321]) # <-- address of the function g + blackholeinterp = getblackholeinterp({'catch_exception/L': 0, + 'residual_call_ir_i/idIR>i': 1, + 'int_return/i': 2, + 'int_return/c': 3}, + [""]) + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, 100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 200 + # + blackholeinterp.setposition(jitcode, 0) + blackholeinterp.setarg_i(0x9, -100) + blackholeinterp.run() + assert blackholeinterp.final_result_i() == 42 + +def test_convert_and_run_from_pyjitpl(): + class MyMIFrame: + jitcode = JitCode("test") + jitcode.setup("\xFF" # illegal instruction + "\x00\x00\x01\x02" # int_add/ii>i + "\x01\x02", # int_return/i + [], + num_regs_i=3, num_regs_r=0, num_regs_f=0) + pc = 1 + registers_i = [history.BoxInt(40), history.ConstInt(2), None] + class MyMetaInterp: + class staticdata: + result_type = 'int' + class profiler: + @staticmethod + def start_blackhole(): pass + @staticmethod + def end_blackhole(): pass + class DoneWithThisFrameInt(Exception): + pass + last_exc_value_box = None + framestack = [MyMIFrame()] + MyMetaInterp.staticdata.blackholeinterpbuilder = getblackholeinterp( + {'int_add/ii>i': 0, 'int_return/i': 1}).builder + MyMetaInterp.staticdata.blackholeinterpbuilder.metainterp_sd = \ + MyMetaInterp.staticdata + # + d = py.test.raises(MyMetaInterp.staticdata.DoneWithThisFrameInt, + convert_and_run_from_pyjitpl, MyMetaInterp()) + assert d.value.args == (42,) + + +class TestBlackhole(LLJitMixin): + + def test_blackholeinterp_cache(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + def choices(x): + if x == 2: return 10 + if x == 3: return 199 + if x == 4: return 124 + if x == 5: return -521 + if x == 6: return 8917 + if x == 7: return -387 + return 34871 + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + y += choices(x) + x -= 1 + return y # - previnit = pyjitpl.MIFrame.__init__.im_func + seen = [] + def my_copy_constants(self, *args): + seen.append(1) + return org_copy_constants(self, *args) + org_copy_constants = BlackholeInterpreter.copy_constants + BlackholeInterpreter.copy_constants = my_copy_constants try: - self.seen_frames = [] - pyjitpl.MIFrame.__init__ = counting_init - return super(BlackholeTests, self).meta_interp(*args) + res = self.meta_interp(f, [7], repeat=7) finally: - pyjitpl.MIFrame.__init__ = previnit - - def test_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - return g() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_indirect_calls_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - def h(): - return 42 - def g(): - return h() - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - call = h - else: - call = g - return call() - res = self.meta_interp(f, [7]) - assert res == 42 - assert self.seen_frames == ['f', 'f'] - - def test_oosends_not_followed(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) - class A: - def meth(self): - return 42 - class B(A): - def meth(self): - return 45 - class C(A): - def meth(self): - return 64 - def f(n): - while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= 1 - if n < 0: - x = B() - else: - x = C() - return x.meth() - res = self.meta_interp(f, [7]) - assert res == 64 - assert self.seen_frames == ['f', 'f'] - - -class TestLLtype(BlackholeTests, LLJitMixin): - pass - -class TestOOtype(BlackholeTests, OOJitMixin): - pass + BlackholeInterpreter.copy_constants = org_copy_constants + # + assert res == sum([choices(x) for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 + assert len(seen) == 2 * 3 + + def test_blackholeinterp_cache_exc(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + class FooError(Exception): + def __init__(self, num): + self.num = num + def choices(x): + if x == 2: raise FooError(10) + if x == 3: raise FooError(199) + if x == 4: raise FooError(124) + if x == 5: raise FooError(-521) + if x == 6: raise FooError(8917) + if x == 7: raise FooError(-387) + raise FooError(34871) + def f(x): + y = 0 + while x > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + try: + choices(x) + except FooError, e: + y += e.num + x -= 1 + return y + res = self.meta_interp(f, [7], repeat=7) + assert res == sum([py.test.raises(FooError, choices, x).value.num + for x in range(1, 8)]) + builder = pyjitpl._warmrunnerdesc.metainterp_sd.blackholeinterpbuilder + assert builder.num_interpreters == 2 Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_compile.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,8 @@ from pypy.jit.metainterp.history import BoxInt from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop -from pypy.jit.metainterp.compile import ResumeGuardDescr, ResumeGuardCounters +from pypy.jit.metainterp.compile import ResumeGuardDescr +from pypy.jit.metainterp.compile import ResumeGuardCountersInt from pypy.jit.metainterp import optimize, jitprof, typesystem from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin @@ -107,49 +108,49 @@ def test_resume_guard_counters(): - rgc = ResumeGuardCounters() + rgc = ResumeGuardCountersInt() # fill in the table for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 1 - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 2 assert rgc.counters == [0] * (4-i) + [2] * (1+i) for i in range(5): - count = rgc.see(BoxInt(100+i)) + count = rgc.see_int(100+i) assert count == 3 # make a distribution: [5, 4, 7, 6, 3] assert rgc.counters == [3, 3, 3, 3, 3] - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 4 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 5 - count = rgc.see(BoxInt(101)) + count = rgc.see_int(101) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 4 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 5 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 6 - count = rgc.see(BoxInt(102)) + count = rgc.see_int(102) assert count == 7 - count = rgc.see(BoxInt(103)) + count = rgc.see_int(103) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 4 - count = rgc.see(BoxInt(104)) + count = rgc.see_int(104) assert count == 5 assert rgc.counters == [5, 4, 7, 6, 3] # the next new item should throw away 104, as 5 is the middle counter - count = rgc.see(BoxInt(190)) + count = rgc.see_int(190) assert count == 1 assert rgc.counters == [1, 4, 7, 6, 3] # the next new item should throw away 103, as 4 is the middle counter - count = rgc.see(BoxInt(191)) + count = rgc.see_int(191) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 3] # the next new item should throw away 100, as 3 is the middle counter - count = rgc.see(BoxInt(192)) + count = rgc.see_int(192) assert count == 1 assert rgc.counters == [1, 1, 7, 6, 1] Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_exception.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,7 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy class ExceptionTests: @@ -516,11 +516,10 @@ assert res == -1 self.check_tree_loop_count(2) # the loop and the entry path # we get: - # ENTER - compile the new loop - # ENTER (BlackHole) - leave - # ENTER - compile the entry bridge - # ENTER - compile the leaving path (raising MyError) - self.check_enter_count(4) + # ENTER - compile the new loop + # ENTER - compile the entry bridge + # ENTER - compile the leaving path (raising MyError) + self.check_enter_count(3) def test_bridge_from_interpreter_exc_2(self): @@ -556,7 +555,6 @@ optimizer=OPTIMIZER_SIMPLE) assert res == 8 - def test_overflowerror_escapes(self): def g(x): return ovfcheck(x + 1) @@ -570,6 +568,26 @@ res = self.interp_operations(f, [sys.maxint]) assert res == -42 + def test_bug_1(self): + def h(i): + if i > 10: + raise ValueError + if i > 5: + raise KeyError + return 5 + def g(i): + try: + return h(i) + except ValueError: + return 21 + def f(i): + try: + return g(i) + except KeyError: + return 42 + res = self.interp_operations(f, [99]) + assert res == 21 + class MyError(Exception): def __init__(self, n): self.n = n Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_executor.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_executor.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_executor.py Sun Jun 20 18:38:42 2010 @@ -1,60 +1,87 @@ import py import sys, random from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.jit.metainterp.executor import make_execute_list, execute +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.executor import execute_varargs, execute_nonspec from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxPtr, ConstPtr from pypy.jit.metainterp.history import BoxFloat, ConstFloat from pypy.jit.metainterp.history import AbstractDescr, Box +from pypy.jit.metainterp import history from pypy.jit.backend.model import AbstractCPU class FakeDescr(AbstractDescr): pass -class FakeBox(Box): +class FakeCallDescr(FakeDescr): + def get_return_type(self): + return history.FLOAT + +class FakeFieldDescr(FakeDescr): + def is_pointer_field(self): + return False + def is_float_field(self): + return True + +class FakeArrayDescr(FakeDescr): + def is_array_of_pointers(self): + return False + def is_array_of_floats(self): + return True + +class FakeResultR: + _TYPE = llmemory.GCREF def __init__(self, *args): - self.args = args + self.fakeargs = args + +class FakeMetaInterp: + pass class FakeCPU(AbstractCPU): supports_floats = True - def do_new(self, descr): - return FakeBox('new', descr) - - def do_arraylen_gc(self, box1, descr): - return FakeBox('arraylen_gc', box1, descr) - - def do_setfield_gc(self, box1, box2, descr): - return FakeBox('setfield_gc', box1, box2, descr) + def bh_new(self, descr): + return FakeResultR('new', descr) - def do_setarrayitem_gc(self, box1, box2, box3, descr): - return FakeBox('setarrayitem_gc', box1, box2, box3, descr) + def bh_arraylen_gc(self, descr, array): + assert not array + assert isinstance(descr, FakeDescr) + return 55 + + def bh_setfield_gc_f(self, struct, fielddescr, newvalue): + self.fakesetfield = (struct, newvalue, fielddescr) + + def bh_setarrayitem_gc_f(self, arraydescr, array, index, newvalue): + self.fakesetarrayitem = (array, index, newvalue, arraydescr) + + def bh_call_f(self, func, calldescr, args_i, args_r, args_f): + self.fakecalled = (func, calldescr, args_i, args_r, args_f) + return 42.5 - def do_call(self, args, descr): - return FakeBox('call', args, descr) - - def do_strsetitem(self, box1, box2, box3): - return FakeBox('strsetitem', box1, box2, box3) - -make_execute_list(FakeCPU) + def bh_strsetitem(self, string, index, newvalue): + self.fakestrsetitem = (string, index, newvalue) def test_execute(): cpu = FakeCPU() descr = FakeDescr() - box = execute(cpu, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) + box = execute(cpu, None, rop.INT_ADD, None, BoxInt(40), ConstInt(2)) assert box.value == 42 - box = execute(cpu, rop.NEW, descr) - assert box.args == ('new', descr) + box = execute(cpu, None, rop.NEW, descr) + assert box.value.fakeargs == ('new', descr) def test_execute_varargs(): cpu = FakeCPU() - descr = FakeDescr() - argboxes = [BoxInt(321), ConstInt(123)] - box = execute_varargs(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + descr = FakeCallDescr() + argboxes = [BoxInt(99999), BoxInt(321), ConstFloat(2.25), ConstInt(123), + BoxPtr(), BoxFloat(5.5)] + box = execute_varargs(cpu, FakeMetaInterp(), rop.CALL, argboxes, descr) + assert box.value == 42.5 + assert cpu.fakecalled == (99999, descr, [321, 123], + [ConstPtr.value], [2.25, 5.5]) def test_execute_nonspec(): cpu = FakeCPU() @@ -62,33 +89,38 @@ # cases with a descr # arity == -1 argboxes = [BoxInt(321), ConstInt(123)] - box = execute_nonspec(cpu, rop.CALL, argboxes, descr) - assert box.args == ('call', argboxes, descr) + box = execute_nonspec(cpu, FakeMetaInterp(), rop.CALL, + argboxes, FakeCallDescr()) + assert box.value == 42.5 # arity == 0 - box = execute_nonspec(cpu, rop.NEW, [], descr) - assert box.args == ('new', descr) + box = execute_nonspec(cpu, None, rop.NEW, [], descr) + assert box.value.fakeargs == ('new', descr) # arity == 1 - box1 = BoxInt(515) - box = execute_nonspec(cpu, rop.ARRAYLEN_GC, [box1], descr) - assert box.args == ('arraylen_gc', box1, descr) + box1 = BoxPtr() + box = execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr) + assert box.value == 55 # arity == 2 - box2 = BoxInt(222) - box = execute_nonspec(cpu, rop.SETFIELD_GC, [box1, box2], descr) - assert box.args == ('setfield_gc', box1, box2, descr) + box2 = BoxFloat(222.2) + fielddescr = FakeFieldDescr() + execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr) + assert cpu.fakesetfield == (box1.value, box2.value, fielddescr) # arity == 3 - box3 = BoxInt(-33) - box = execute_nonspec(cpu, rop.SETARRAYITEM_GC, [box1, box2, box3], descr) - assert box.args == ('setarrayitem_gc', box1, box2, box3, descr) + box3 = BoxInt(33) + arraydescr = FakeArrayDescr() + execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2], + arraydescr) + assert cpu.fakesetarrayitem == (box1.value, box3.value, box2.value, + arraydescr) # cases without descr # arity == 1 - box = execute_nonspec(cpu, rop.INT_INVERT, [box1]) - assert box.value == ~515 + box = execute_nonspec(cpu, None, rop.INT_INVERT, [box3]) + assert box.value == ~33 # arity == 2 - box = execute_nonspec(cpu, rop.INT_LSHIFT, [box1, BoxInt(3)]) - assert box.value == 515 << 3 + box = execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, BoxInt(3)]) + assert box.value == 33 << 3 # arity == 3 - box = execute_nonspec(cpu, rop.STRSETITEM, [box1, box2, box3]) - assert box.args == ('strsetitem', box1, box2, box3) + execute_nonspec(cpu, None, rop.STRSETITEM, [box1, BoxInt(3), box3]) + assert cpu.fakestrsetitem == (box1.value, 3, box3.value) # ints @@ -181,7 +213,7 @@ (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]), (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]), (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]), - (rop.BOOL_NOT, [(0, 1), (1, 0)]), + (rop.INT_IS_ZERO, [(0, 1), (1, 0), (2, 0), (-1, 0), (minint, 0)]), ]: for x, y in testcases: yield opnum, [x], y @@ -204,7 +236,7 @@ def test_int_ops(): cpu = FakeCPU() for opnum, boxargs, retvalue in get_int_tests(): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) assert box.getint() == retvalue # floats @@ -242,9 +274,6 @@ yield (rop.FLOAT_NEG, [15.9], 'float', -15.9) yield (rop.FLOAT_ABS, [-5.9], 'float', 5.9) yield (rop.FLOAT_ABS, [15.9], 'float', 15.9) - yield (rop.FLOAT_IS_TRUE, [-5.9], 'int', 1) - yield (rop.FLOAT_IS_TRUE, [0.0], 'int', 0) - yield (rop.FLOAT_IS_TRUE, [-0.0], 'int', 0) yield (rop.CAST_FLOAT_TO_INT, [-5.9], 'int', -5) yield (rop.CAST_FLOAT_TO_INT, [5.9], 'int', 5) yield (rop.CAST_INT_TO_FLOAT, [123], 'float', 123.0) @@ -276,7 +305,7 @@ def test_float_ops(): cpu = FakeCPU() for opnum, boxargs, rettype, retvalue in get_float_tests(cpu): - box = execute_nonspec(cpu, opnum, boxargs) + box = execute_nonspec(cpu, None, opnum, boxargs) if rettype == 'float': assert box.getfloat() == retvalue elif rettype == 'int': Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_history.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_history.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_history.py Sun Jun 20 18:38:42 2010 @@ -9,10 +9,3 @@ s = lltype.cast_pointer(lltype.Ptr(S), t) const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)) assert const._getrepr_() == "*T" - -def test_slicing(): - h = History() - h.operations = [1, 2, 3, 4, 5] - rest = h.slice_history_at(2) - assert rest == [4, 5] - assert h.operations == [1, 2] Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_jitprof.py Sun Jun 20 18:38:42 2010 @@ -63,7 +63,7 @@ ] assert profiler.events == expected assert profiler.times == [2, 1, 1, 1] - assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0, + assert profiler.counters == [1, 1, 1, 1, 3, 3, 1, 7, 1, 0, 0, 0, 0, 0, 0, 0] def test_simple_loop_with_call(self): @@ -84,8 +84,7 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[1, 0], [1, 0], [0, 0]] + assert profiler.calls == 1 def test_blackhole_pure(self): @purefunction @@ -99,12 +98,10 @@ myjitdriver.can_enter_jit(x=x, y=y, res=res, z=z) myjitdriver.jit_merge_point(x=x, y=y, res=res, z=z) res += x - if y == 1: - res += g(z) + res += g(z) y -= 1 return res * 2 res = self.meta_interp(f, [6, 7, 2]) - assert res == 90 + assert res == f(6, 7, 2) profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - # calls = (executed, recorded, blackholed) x (inpure, pure) - assert profiler.calls == [[0, 1], [0, 0], [0, 1]] + assert profiler.calls == 1 Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py Sun Jun 20 18:38:42 2010 @@ -1,7 +1,5 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_loop.py Sun Jun 20 18:38:42 2010 @@ -2,9 +2,8 @@ from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.objectmodel import compute_hash from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats -from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp import history @@ -342,7 +341,7 @@ assert res == expected def test_loop_unicode(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = u'' while n > 13: @@ -356,7 +355,7 @@ assert res == expected def test_loop_string(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def f(n): x = '' while n > 13: Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefindnode.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefindnode.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizefindnode.py Sun Jun 20 18:38:42 2010 @@ -6,7 +6,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - Const, ConstAddr, TreeLoop, BoxObj, + Const, TreeLoop, BoxObj, ConstObj, AbstractDescr) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder @@ -16,7 +16,8 @@ from pypy.jit.metainterp.specnode import VirtualArraySpecNode from pypy.jit.metainterp.specnode import VirtualStructSpecNode from pypy.jit.metainterp.specnode import ConstantSpecNode -from pypy.jit.metainterp.effectinfo import EffectInfo +from pypy.jit.codewriter.effectinfo import EffectInfo +from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int from pypy.jit.metainterp.test.oparser import parse def test_sort_descrs(): @@ -113,7 +114,7 @@ EffectInfo([adescr], [], [])) mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo([nextdescr], [], [], - forces_virtual_or_virtualizable=True)) + EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)) class LoopToken(AbstractDescr): pass asmdescr = LoopToken() # it can be whatever, it's not a descr though @@ -129,83 +130,81 @@ jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable) - cpu.class_sizes = { - cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE), - cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2), - cpu.cast_adr_to_int(u_vtable_adr): cpu.sizeof(U), - cpu.cast_adr_to_int(jvr_vtable_adr): cpu.sizeof( - vrefinfo.JIT_VIRTUAL_REF), - } + register_known_gctype(cpu, node_vtable, NODE) + register_known_gctype(cpu, node_vtable2, NODE2) + register_known_gctype(cpu, u_vtable, U) + register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF) + namespace = locals() -class OOtypeMixin(object): +class OOtypeMixin_xxx_disabled(object): type_system = 'ootype' - def get_class_of_box(self, box): - root = box.getref(ootype.ROOT) - return ootype.classof(root) +## def get_class_of_box(self, box): +## root = box.getref(ootype.ROOT) +## return ootype.classof(root) - cpu = runner.OOtypeCPU(None) - NODE = ootype.Instance('NODE', ootype.ROOT, {}) - NODE._add_fields({'value': ootype.Signed, - 'floatval' : ootype.Float, - 'next': NODE}) - NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) - - node_vtable = ootype.runtimeClass(NODE) - node_vtable_adr = ootype.cast_to_object(node_vtable) - node_vtable2 = ootype.runtimeClass(NODE2) - node_vtable_adr2 = ootype.cast_to_object(node_vtable2) - - node = ootype.new(NODE) - nodebox = BoxObj(ootype.cast_to_object(node)) - myptr = nodebox.value - myptr2 = ootype.cast_to_object(ootype.new(NODE)) - nodebox2 = BoxObj(ootype.cast_to_object(node)) - valuedescr = cpu.fielddescrof(NODE, 'value') - floatdescr = cpu.fielddescrof(NODE, 'floatval') - nextdescr = cpu.fielddescrof(NODE, 'next') - otherdescr = cpu.fielddescrof(NODE2, 'other') - nodesize = cpu.typedescrof(NODE) - nodesize2 = cpu.typedescrof(NODE2) - - arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) - floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) - - # a plain Record - S = ootype.Record({'a': ootype.Signed, 'b': NODE}) - ssize = cpu.typedescrof(S) - adescr = cpu.fielddescrof(S, 'a') - bdescr = cpu.fielddescrof(S, 'b') - sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) - arraydescr2 = cpu.arraydescrof(ootype.Array(S)) - - T = ootype.Record({'c': ootype.Signed, - 'd': ootype.Array(NODE)}) - tsize = cpu.typedescrof(T) - cdescr = cpu.fielddescrof(T, 'c') - ddescr = cpu.fielddescrof(T, 'd') - arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) - - U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) - usize = cpu.typedescrof(U) - onedescr = cpu.fielddescrof(U, 'one') - u_vtable = ootype.runtimeClass(U) - u_vtable_adr = ootype.cast_to_object(u_vtable) - - # force a consistent order - valuedescr.sort_key() - nextdescr.sort_key() - adescr.sort_key() - bdescr.sort_key() - - FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) - nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype - - cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), - node_vtable_adr2: cpu.typedescrof(NODE2), - u_vtable_adr: cpu.typedescrof(U)} - namespace = locals() +## cpu = runner.OOtypeCPU(None) +## NODE = ootype.Instance('NODE', ootype.ROOT, {}) +## NODE._add_fields({'value': ootype.Signed, +## 'floatval' : ootype.Float, +## 'next': NODE}) +## NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE}) + +## node_vtable = ootype.runtimeClass(NODE) +## node_vtable_adr = ootype.cast_to_object(node_vtable) +## node_vtable2 = ootype.runtimeClass(NODE2) +## node_vtable_adr2 = ootype.cast_to_object(node_vtable2) + +## node = ootype.new(NODE) +## nodebox = BoxObj(ootype.cast_to_object(node)) +## myptr = nodebox.value +## myptr2 = ootype.cast_to_object(ootype.new(NODE)) +## nodebox2 = BoxObj(ootype.cast_to_object(node)) +## valuedescr = cpu.fielddescrof(NODE, 'value') +## floatdescr = cpu.fielddescrof(NODE, 'floatval') +## nextdescr = cpu.fielddescrof(NODE, 'next') +## otherdescr = cpu.fielddescrof(NODE2, 'other') +## nodesize = cpu.typedescrof(NODE) +## nodesize2 = cpu.typedescrof(NODE2) + +## arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed)) +## floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float)) + +## # a plain Record +## S = ootype.Record({'a': ootype.Signed, 'b': NODE}) +## ssize = cpu.typedescrof(S) +## adescr = cpu.fielddescrof(S, 'a') +## bdescr = cpu.fielddescrof(S, 'b') +## sbox = BoxObj(ootype.cast_to_object(ootype.new(S))) +## arraydescr2 = cpu.arraydescrof(ootype.Array(S)) + +## T = ootype.Record({'c': ootype.Signed, +## 'd': ootype.Array(NODE)}) +## tsize = cpu.typedescrof(T) +## cdescr = cpu.fielddescrof(T, 'c') +## ddescr = cpu.fielddescrof(T, 'd') +## arraydescr3 = cpu.arraydescrof(ootype.Array(NODE)) + +## U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)}) +## usize = cpu.typedescrof(U) +## onedescr = cpu.fielddescrof(U, 'one') +## u_vtable = ootype.runtimeClass(U) +## u_vtable_adr = ootype.cast_to_object(u_vtable) + +## # force a consistent order +## valuedescr.sort_key() +## nextdescr.sort_key() +## adescr.sort_key() +## bdescr.sort_key() + +## FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) +## nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype + +## cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE), +## node_vtable_adr2: cpu.typedescrof(NODE2), +## u_vtable_adr: cpu.typedescrof(U)} +## namespace = locals() class BaseTest(object): invent_fail_descr = None @@ -220,8 +219,7 @@ # def constclass(cls_vtable): if self.type_system == 'lltype': - return ConstAddr(llmemory.cast_ptr_to_adr(cls_vtable), - self.cpu) + return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable))) else: return ConstObj(ootype.cast_to_object(cls_vtable)) def constant(value): @@ -357,7 +355,7 @@ assert not boxp2.fromstart assert boxp1.knownclsbox is None - assert boxp2.knownclsbox.value == self.node_vtable_adr + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr def test_find_nodes_new_2(self): ops = """ @@ -413,8 +411,8 @@ assert not boxp2.fromstart assert not boxp3.fromstart - assert boxp2.knownclsbox.value == self.node_vtable_adr - assert boxp3.knownclsbox.value == self.node_vtable_adr2 + assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr + assert boxp3.knownclsbox.getaddr() == self.node_vtable_adr2 def test_find_nodes_new_aliasing_0(self): ops = """ @@ -503,31 +501,31 @@ nextdescr=Virtual(node_vtable, nextdescr=Virtual(node_vtable)))''') - def test_find_nodes_oois(self): + def test_find_nodes_ptr_eq(self): ops = """ [p3, p4, p2] p0 = new_with_vtable(ConstClass(node_vtable)) p1 = new_with_vtable(ConstClass(node_vtable)) guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -1160,14 +1158,13 @@ class TestLLtype(BaseTestOptimizeFindNode, LLtypeMixin): pass -class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): - - def test_find_nodes_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - boxes, getnode = self.find_nodes(ops, 'Not') - assert not getnode(boxes.p0).escaped +##class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin): +## def test_find_nodes_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## boxes, getnode = self.find_nodes(ops, 'Not') +## assert not getnode(boxes.p0).escaped Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py Sun Jun 20 18:38:42 2010 @@ -1,8 +1,7 @@ import py from pypy.rlib.objectmodel import instantiate -from pypy.jit.metainterp.test.test_resume import MyMetaInterp from pypy.jit.metainterp.test.test_optimizefindnode import (LLtypeMixin, - OOtypeMixin, + #OOtypeMixin, BaseTest) from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder from pypy.jit.metainterp import optimizeopt @@ -10,18 +9,17 @@ from pypy.jit.metainterp.optimizeutil import InvalidLoop from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from pypy.jit.metainterp.jitprof import EmptyProfiler -from pypy.jit.metainterp import executor, compile, resume +from pypy.jit.metainterp import executor, compile, resume, history from pypy.jit.metainterp.resoperation import rop, opname, ResOperation from pypy.jit.metainterp.test.oparser import pure_parse -class FakeFrame(object): - parent_resumedata_snapshot = None - parent_resumedata_frame_info_list = None - - def __init__(self, code="", pc=0, exc_target=-1): - self.jitcode = code - self.pc = pc - self.exception_target = exc_target +##class FakeFrame(object): +## parent_resumedata_snapshot = None +## parent_resumedata_frame_info_list = None + +## def __init__(self, code="", pc=0): +## self.jitcode = code +## self.pc = pc class Fake(object): failargs_limit = 1000 @@ -45,9 +43,8 @@ fdescr = ResumeGuardDescr(None, None) op = ResOperation(rop.GUARD_TRUE, [], None, descr=fdescr) # setup rd data - fi0 = resume.FrameInfo(None, FakeFrame("code0", 1, 2)) - fdescr.rd_frame_info_list = resume.FrameInfo(fi0, - FakeFrame("code1", 3, -1)) + fi0 = resume.FrameInfo(None, "code0", 11) + fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) snapshot0 = resume.Snapshot(None, [b0]) fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1]) # @@ -215,14 +212,18 @@ def __eq__(self, other): return type(self) is type(other) # xxx obscure +def _sortboxes(boxes): + _kind2count = {history.INT: 1, history.REF: 2, history.FLOAT: 3} + return sorted(boxes, key=lambda box: _kind2count[box.type]) + class BaseTestOptimizeOpt(BaseTest): def invent_fail_descr(self, fail_args): if fail_args is None: return None descr = Storage() - descr.rd_frame_info_list = resume.FrameInfo(None, FakeFrame()) - descr.rd_snapshot = resume.Snapshot(None, fail_args) + descr.rd_frame_info_list = resume.FrameInfo(None, "code", 11) + descr.rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args)) return descr def assert_equal(self, optimized, expected): @@ -273,7 +274,7 @@ i0 = int_add(2, 3) i1 = int_is_true(i0) guard_true(i1) [] - i2 = bool_not(i1) + i2 = int_is_zero(i1) guard_false(i2) [] guard_value(i0, 5) [] jump() @@ -289,7 +290,7 @@ from pypy.jit.metainterp.executor import execute_nonspec from pypy.jit.metainterp.history import BoxInt import random - for opnum in range(rop.INT_ADD, rop.BOOL_NOT+1): + for opnum in range(rop.INT_ADD, rop.SAME_AS+1): try: op = opname[opnum] except KeyError: @@ -309,7 +310,7 @@ jump() """ % (op.lower(), ', '.join(map(str, args))) argboxes = [BoxInt(a) for a in args] - expected_value = execute_nonspec(self.cpu, opnum, + expected_value = execute_nonspec(self.cpu, None, opnum, argboxes).getint() expected = """ [] @@ -410,7 +411,7 @@ self.optimize_loop(ops, 'Not', expected) def test_int_is_true_1(self): - py.test.skip("too bad") + py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -427,6 +428,24 @@ """ self.optimize_loop(ops, 'Not', expected) + def test_int_is_true_is_zero(self): + py.test.skip("XXX implement me") + ops = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + expected = """ + [i0] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + self.optimize_loop(ops, 'Not', expected) + def test_ooisnull_oononnull_2(self): ops = """ [p0] @@ -478,13 +497,13 @@ ops = """ [p0] guard_class(p0, ConstClass(node_vtable)) [] - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] jump(p0) """ @@ -499,13 +518,13 @@ ops = """ [p0] setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL - i0 = ooisnot(p0, NULL) + i0 = ptr_ne(p0, NULL) guard_true(i0) [] - i1 = oois(p0, NULL) + i1 = ptr_eq(p0, NULL) guard_false(i1) [] - i2 = ooisnot(NULL, p0) + i2 = ptr_ne(NULL, p0) guard_true(i0) [] - i3 = oois(NULL, p0) + i3 = ptr_eq(NULL, p0) guard_false(i1) [] guard_nonnull(p0) [] jump(p0) @@ -578,6 +597,25 @@ """ self.optimize_loop(ops, 'Not', ops) + def test_int_is_true_of_bool(self): + ops = """ + [i0, i1] + i2 = int_gt(i0, i1) + i3 = int_is_true(i2) + i4 = int_is_true(i3) + guard_value(i4, 0) [i0, i1] + jump(i0, i1) + """ + expected = """ + [i0, i1] + i2 = int_gt(i0, i1) + guard_false(i2) [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, 'Not, Not', expected) + + + def test_p123_simple(self): ops = """ @@ -728,25 +766,25 @@ ops = """ [p0, p1, p2] guard_nonnull(p0) [] - i3 = ooisnot(p0, NULL) + i3 = ptr_ne(p0, NULL) guard_true(i3) [] - i4 = oois(p0, NULL) + i4 = ptr_eq(p0, NULL) guard_false(i4) [] - i5 = ooisnot(NULL, p0) + i5 = ptr_ne(NULL, p0) guard_true(i5) [] - i6 = oois(NULL, p0) + i6 = ptr_eq(NULL, p0) guard_false(i6) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -766,17 +804,17 @@ expected2 = """ [p0, p1, p2] guard_nonnull(p0) [] - i7 = ooisnot(p0, p1) + i7 = ptr_ne(p0, p1) guard_true(i7) [] - i8 = oois(p0, p1) + i8 = ptr_eq(p0, p1) guard_false(i8) [] - i9 = ooisnot(p0, p2) + i9 = ptr_ne(p0, p2) guard_true(i9) [] - i10 = oois(p0, p2) + i10 = ptr_eq(p0, p2) guard_false(i10) [] - i11 = ooisnot(p2, p1) + i11 = ptr_ne(p2, p1) guard_true(i11) [] - i12 = oois(p2, p1) + i12 = ptr_eq(p2, p1) guard_false(i12) [] jump(p0, p1, p2) """ @@ -870,7 +908,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, NULL, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -886,7 +924,7 @@ p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, ConstPtr(myptr), descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p2, NULL) + i1 = ptr_eq(p2, NULL) jump(i1) """ expected = """ @@ -1514,7 +1552,7 @@ """ expected = """ [p1, i2, i3] - guard_true(i3) [p1, i2] + guard_true(i3) [i2, p1] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) @@ -1920,7 +1958,7 @@ ops = """ [p1] guard_class(p1, ConstClass(node_vtable2)) [] - i = ooisnot(ConstPtr(myptr), p1) + i = ptr_ne(ConstPtr(myptr), p1) guard_true(i) [] jump(p1) """ @@ -1936,9 +1974,9 @@ [p0] p1 = getfield_gc(p0, descr=nextdescr) p2 = getfield_gc(p0, descr=nextdescr) - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) guard_true(i1) [] - i2 = ooisnot(p1, p2) + i2 = ptr_ne(p1, p2) guard_false(i2) [] jump(p0) """ @@ -1952,8 +1990,8 @@ def test_remove_duplicate_pure_op(self): ops = """ [p1, p2] - i1 = oois(p1, p2) - i2 = oois(p1, p2) + i1 = ptr_eq(p1, p2) + i2 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -1968,7 +2006,7 @@ """ expected = """ [p1, p2] - i1 = oois(p1, p2) + i1 = ptr_eq(p1, p2) i3 = int_add(i1, 1) i3b = int_is_true(i3) guard_true(i3b) [] @@ -2024,7 +2062,7 @@ # typically called twice, before and after optimization if self.oparse is None: fdescr.rd_frame_info_list = resume.FrameInfo(None, - FakeFrame()) + "code", 11) fdescr.rd_snapshot = resume.Snapshot(None, fail_args) self.oparse = oparse # @@ -2096,7 +2134,7 @@ for pvar, pfieldname, pfieldvar in pendingfields: box = oparse.getvar(pvar) fielddescr = self.namespace[pfieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, box) @@ -2114,13 +2152,13 @@ if tag[0] in ('virtual', 'vstruct'): fieldname, fieldvalue = fieldtext.split('=') fielddescr = self.namespace[fieldname.strip()] - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC, fielddescr, resolved) elif tag[0] == 'varray': fieldvalue = fieldtext - fieldbox = executor.execute(self.cpu, + fieldbox = executor.execute(self.cpu, None, rop.GETARRAYITEM_GC, tag[1], resolved, ConstInt(index)) @@ -2130,12 +2168,14 @@ index += 1 def check_expanded_fail_descr(self, expectedtext, guard_opnum): + from pypy.jit.metainterp.test.test_resume import ResumeDataFakeReader + from pypy.jit.metainterp.test.test_resume import MyMetaInterp guard_op, = [op for op in self.loop.operations if op.is_guard()] fail_args = guard_op.fail_args fdescr = guard_op.descr assert fdescr.guard_opnum == guard_opnum - reader = resume.ResumeDataReader(fdescr, fail_args, - MyMetaInterp(self.cpu)) + reader = ResumeDataFakeReader(fdescr, fail_args, + MyMetaInterp(self.cpu)) boxes = reader.consume_boxes() self._verify_fail_args(boxes, fdescr.oparse, expectedtext) @@ -2190,7 +2230,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p3, descr=nextdescr) - guard_true(i1, descr=fdescr) [p1, i3] + guard_true(i1, descr=fdescr) [i3, p1] jump(i2, i1, i3, p3) """ expected = """ @@ -2199,15 +2239,14 @@ jump(i2, 1, i3, p3) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3 + self.check_expanded_fail_descr('''i3, p1 where p1 is a node_vtable, valuedescr=1, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p3 ''', rop.GUARD_TRUE) def test_expand_fail_4(self): - for arg in ['p1', 'p1,i2', 'i2,p1', 'p1,p2', 'p2,p1', - 'p1,p2,i2', 'p1,i2,p2', 'p2,p1,i2', - 'p2,i2,p1', 'i2,p1,p2', 'i2,p2,p1']: + for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1', + 'i2,p1,p2', 'i2,p2,p1']: self.make_fail_descr() ops = """ [i1, i2, i3] @@ -2218,7 +2257,7 @@ setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) - guard_true(i1, descr=fdescr) [i4, %s, i3] + guard_true(i1, descr=fdescr) [i4, i3, %s] jump(i1, i2, i3) """ expected = """ @@ -2227,7 +2266,7 @@ jump(1, i2, i3) """ self.optimize_loop(ops % arg, 'Not, Not, Not', expected) - self.check_expanded_fail_descr('''i3, %s, i3 + self.check_expanded_fail_descr('''i3, i3, %s where p1 is a node_vtable, valuedescr=i2, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2''' % arg, rop.GUARD_TRUE) @@ -2242,7 +2281,7 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p1, descr=nextdescr) # a cycle - guard_true(i1, descr=fdescr) [p1, i3, p2, i4] + guard_true(i1, descr=fdescr) [i3, i4, p1, p2] jump(i2, i1, i3, i4) """ expected = """ @@ -2251,7 +2290,7 @@ jump(i2, 1, i3, i4) """ self.optimize_loop(ops, 'Not, Not, Not, Not', expected) - self.check_expanded_fail_descr('''p1, i3, p2, i4 + self.check_expanded_fail_descr('''i3, i4, p1, p2 where p1 is a node_vtable, valuedescr=i4, nextdescr=p2 where p2 is a node_vtable, valuedescr=i2, nextdescr=p1 ''', rop.GUARD_TRUE) @@ -2587,14 +2626,45 @@ self.optimize_loop(ops, 'Not, Not', ops) def test_call_pure_invalidates_caches(self): + # CALL_PURE should still force the setfield_gc() to occur before it ops = ''' [p1, i1] setfield_gc(p1, i1, descr=valuedescr) - i3 = call_pure(p1, descr=plaincalldescr) + i3 = call_pure(42, p1, descr=plaincalldescr) + setfield_gc(p1, i3, descr=valuedescr) + jump(p1, i3) + ''' + expected = ''' + [p1, i1] + setfield_gc(p1, i1, descr=valuedescr) + i3 = call(p1, descr=plaincalldescr) setfield_gc(p1, i3, descr=valuedescr) jump(p1, i3) ''' - self.optimize_loop(ops, 'Not, Not', ops) + self.optimize_loop(ops, 'Not, Not', expected) + + def test_call_pure_constant_folding(self): + # CALL_PURE is not marked as is_always_pure(), because it is wrong + # to call the function arbitrary many times at arbitrary points in + # time. Check that it is either constant-folded (and replaced by + # the result of the call, recorded as the first arg), or turned into + # a regular CALL. + ops = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i3 = call_pure(42, 123456, 4, 5, 6, descr=plaincalldescr) + i4 = call_pure(43, 123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, i3, i4) + ''' + expected = ''' + [i0, i1, i2] + escape(i1) + escape(i2) + i4 = call(123456, 4, i0, 6, descr=plaincalldescr) + jump(i0, 42, i4) + ''' + self.optimize_loop(ops, 'Not, Not, Not', expected) def test_vref_nonvirtual_nonescape(self): ops = """ @@ -2626,7 +2696,7 @@ setfield_gc(p2, 5, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p1) """ # XXX we should optimize a bit more the case of a nonvirtual. @@ -2668,7 +2738,7 @@ setfield_gc(p1b, 252, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ self.optimize_loop(ops, 'Not, Not', expected) @@ -2709,7 +2779,7 @@ setfield_gc(p1b, i1, descr=valuedescr) setfield_gc(p1, p1b, descr=nextdescr) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) jump(p0, i1) """ # the point of this test is that 'i1' should show up in the fail_args @@ -2780,7 +2850,7 @@ escape(p2) p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [] jump(i1) @@ -2806,7 +2876,7 @@ setfield_gc(p2, 23, descr=virtualrefindexdescr) escape(p2) setfield_gc(p2, p1, descr=virtualforceddescr) - setfield_gc(p2, -2, descr=virtualtokendescr) + setfield_gc(p2, -3, descr=virtualtokendescr) call_may_force(i1, descr=mayforcevirtdescr) guard_not_forced() [i1] jump(i1, p1) @@ -2880,31 +2950,31 @@ ''' self.optimize_loop(ops, 'Not', expected) -class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): +##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin): - def test_instanceof(self): - ops = """ - [i0] - p0 = new_with_vtable(ConstClass(node_vtable)) - i1 = instanceof(p0, descr=nodesize) - jump(i1) - """ - expected = """ - [i0] - jump(1) - """ - self.optimize_loop(ops, 'Not', expected) +## def test_instanceof(self): +## ops = """ +## [i0] +## p0 = new_with_vtable(ConstClass(node_vtable)) +## i1 = instanceof(p0, descr=nodesize) +## jump(i1) +## """ +## expected = """ +## [i0] +## jump(1) +## """ +## self.optimize_loop(ops, 'Not', expected) - def test_instanceof_guard_class(self): - ops = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - i1 = instanceof(p0, descr=nodesize) - jump(i1, p0) - """ - expected = """ - [i0, p0] - guard_class(p0, ConstClass(node_vtable)) [] - jump(1, p0) - """ - self.optimize_loop(ops, 'Not, Not', expected) +## def test_instanceof_guard_class(self): +## ops = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## i1 = instanceof(p0, descr=nodesize) +## jump(i1, p0) +## """ +## expected = """ +## [i0, p0] +## guard_class(p0, ConstClass(node_vtable)) [] +## jump(1, p0) +## """ +## self.optimize_loop(ops, 'Not, Not', expected) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_pyjitpl.py Sun Jun 20 18:38:42 2010 @@ -1,49 +1,20 @@ # some unit tests for the bytecode decoding -from pypy.jit.metainterp import pyjitpl, codewriter, resoperation, history +from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp import jitprof -from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.history import History from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.test.test_optimizeopt import equaloplists +from pypy.jit.codewriter.jitcode import JitCode -def make_frame(code): - bytecode = codewriter.JitCode("hello") - bytecode.code = code - bytecode.constants = None - frame = pyjitpl.MIFrame(None, bytecode) - frame.pc = 0 - return frame - - -def test_decode_big_int(): - for code, value in [("\x80\x01", 128), ("\x81\x81\x01", 1 + (1 << 7) + (1 << 14))]: - frame = make_frame(code) - val = frame.load_int() - assert val == value - -def test_decode_bool(): - frame = make_frame("\x00") - assert not frame.load_bool() - - frame = make_frame("\x01") - assert frame.load_bool() - -def test_simple_opimpl_exist(): - rop = resoperation.rop - for opnum, opname in resoperation.opname.items(): - if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE, - rop.FORCE_TOKEN): - continue - if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST: - assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname def test_portal_trace_positions(): - jitcode = codewriter.JitCode("f") - jitcode.code = jitcode.constants = None - portal = codewriter.JitCode("portal") - portal.code = portal.constants = None + jitcode = JitCode("f") + jitcode.setup(None) + portal = JitCode("portal") + portal.setup(None) class FakeStaticData: cpu = None portal_code = portal @@ -95,7 +66,7 @@ c3 = ConstInt(3) boxes = [b1, b2, b1, c3] dup = {} - metainterp.remove_consts_and_duplicates(boxes, 0, 4, dup) + metainterp.remove_consts_and_duplicates(boxes, 4, dup) assert boxes[0] is b1 assert boxes[1] is b2 assert is_another_box_like(boxes[2], b1) @@ -108,12 +79,12 @@ # del metainterp.history.operations[:] b4 = BoxInt(4) - boxes = ["something random", b2, b4, "something else"] - metainterp.remove_consts_and_duplicates(boxes, 1, 3, dup) - assert is_another_box_like(boxes[1], b2) - assert boxes[2] is b4 + boxes = [b2, b4, "something random"] + metainterp.remove_consts_and_duplicates(boxes, 2, dup) + assert is_another_box_like(boxes[0], b2) + assert boxes[1] is b4 assert equaloplists(metainterp.history.operations, [ - ResOperation(rop.SAME_AS, [b2], boxes[1]), + ResOperation(rop.SAME_AS, [b2], boxes[0]), ]) def test_get_name_from_address(): @@ -121,42 +92,7 @@ def __init__(self): pass metainterp_sd = FakeMetaInterpSd() - metainterp_sd.info_from_codewriter(None, None, - [(123, "a"), (456, "b")], - None) + metainterp_sd.setup_list_of_addr2name([(123, 'a'), (456, 'b')]) assert metainterp_sd.get_name_from_address(123) == 'a' assert metainterp_sd.get_name_from_address(456) == 'b' assert metainterp_sd.get_name_from_address(789) == '' - -def test_initialize_state_from_guard_failure(): - from pypy.jit.metainterp.typesystem import llhelper - calls = [] - - class FakeCPU: - ts = llhelper - - def make_boxes_from_latest_values(self, faildescr): - return [BoxInt(0), None, BoxInt(2), None, BoxInt(4)] - - class FakeStaticData: - cpu = FakeCPU() - profiler = jitprof.EmptyProfiler() - - metainterp = pyjitpl.MetaInterp(FakeStaticData()) - - def rebuild_state_after_failure(descr, newboxes): - calls.append(newboxes) - metainterp.rebuild_state_after_failure = rebuild_state_after_failure - - class FakeResumeDescr: - def must_compile(self, *args): - return True - resumedescr = FakeResumeDescr() - metainterp.initialize_state_from_guard_failure(resumedescr) - - inp = metainterp.history.inputargs - assert len(inp) == 3 - assert [box.value for box in inp] == [0, 2, 4] - b0, b2, b4 = inp - assert len(calls) == 1 - assert calls[0] == [b0, None, b2, None, b4] Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py Sun Jun 20 18:38:42 2010 @@ -1,7 +1,9 @@ import py from pypy.rlib.jit import JitDriver, we_are_jitted, OPTIMIZER_SIMPLE, hint +from pypy.rlib.jit import unroll_safe, dont_look_inside +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.annlowlevel import hlstr from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats @@ -24,6 +26,7 @@ return 1 res = self.meta_interp(main, [20], optimizer=OPTIMIZER_SIMPLE) assert res == main(20) + self.check_history(call=0) def test_simple_recursion_with_exc(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm']) @@ -105,11 +108,11 @@ def can_inline(*args): return True else: - def can_inline(code, i): + def can_inline(i, code): code = hlstr(code) return not JUMP_BACK in code - jitdriver = JitDriver(greens = ['code', 'i'], reds = ['n'], + jitdriver = JitDriver(greens = ['i', 'code'], reds = ['n'], can_inline = can_inline) def interpret(codenum, n, i): @@ -177,13 +180,12 @@ py.test.fail("DID NOT RAISE") def test_guard_failure_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -214,13 +216,12 @@ assert res == 0 def test_guard_failure_and_then_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n', 'flag'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n', 'flag'], get_printable_location=p, can_inline=c) def f(code, n): pc = 0 @@ -258,13 +259,12 @@ assert res == main(1000) def test_exception_in_inlined_function(self): - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) class Exc(Exception): @@ -304,13 +304,12 @@ # this passes, if the blackholing shortcut for calls is turned off # it fails, it is very delicate in terms of parameters, # bridge/loop creation order - from pypy.rpython.annlowlevel import hlstr - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -394,9 +393,36 @@ self.check_aborted_count(8) self.check_enter_count_at_most(30) + def test_trace_limit_with_exception_bug(self): + myjitdriver = JitDriver(greens=[], reds=['n']) + @unroll_safe + def do_stuff(n): + while n > 0: + n -= 1 + raise ValueError + def loop(n): + pc = 0 + while n > 80: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + try: + do_stuff(n) + except ValueError: + # the trace limit is checked when we arrive here, and we + # have the exception still in last_exc_value_box at this + # point -- so when we abort because of a trace too long, + # the exception is passed to the blackhole interp and + # incorrectly re-raised from here + pass + n -= 1 + return n + TRACE_LIMIT = 66 + res = self.meta_interp(loop, [100], trace_limit=TRACE_LIMIT) + assert res == 80 + def test_max_failure_args(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -429,7 +455,7 @@ def test_max_failure_args_exc(self): FAILARGS_LIMIT = 10 - jitdriver = JitDriver(greens = [], reds = ['o', 'i', 'n']) + jitdriver = JitDriver(greens = [], reds = ['i', 'n', 'o']) class A(object): def __init__(self, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9): @@ -495,12 +521,12 @@ self.check_loops(call_may_force=0, call=0) def test_trace_from_start(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -535,12 +561,12 @@ self.check_history(int_add=1) def test_dont_inline_huge_stuff(self): - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['n'], get_printable_location=p, can_inline=c) def f(code, n): @@ -693,7 +719,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -721,6 +747,60 @@ res = self.meta_interp(main, [0], inline=True) assert res == main(0) + def test_directly_call_assembler_virtualizable_reset_token(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rlib.debug import llinterpcall + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno : str(codeno), + can_inline = lambda codeno : False) + + @dont_look_inside + def check_frame(subframe): + if we_are_translated(): + llinterpcall(lltype.Void, check_ll_frame, subframe) + def check_ll_frame(ll_subframe): + # This is called with the low-level Struct that is the frame. + # Check that the vable_token was correctly reset to zero. + # Note that in order for that test to catch failures, it needs + # three levels of recursion: the vable_token of the subframe + # at the level 2 is set to a non-zero value when doing the + # call to the level 3 only. This used to fail when the test + # is run via pypy.jit.backend.x86.test.test_recursive. + assert ll_subframe.vable_token == 0 + + def main(codeno): + frame = Frame() + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 5: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno < 2: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(codeno + 1, subframe) + check_frame(subframe) + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + res = self.meta_interp(main, [0], inline=True) + assert res == main(0) + def test_directly_call_assembler_virtualizable_force(self): class Thing(object): def __init__(self, val): @@ -729,7 +809,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) @@ -770,7 +850,7 @@ assert res == main(0) def test_directly_call_assembler_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = ['codeno'], reds = ['n', 'x', 'frame'], virtualizables = ['frame'], can_inline = lambda codeno : False) @@ -816,7 +896,7 @@ class Frame(object): _virtualizable2_ = ['thing'] - driver = JitDriver(greens = ['codeno'], reds = ['frame', 'i'], + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno : str(codeno), can_inline = lambda codeno : False) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_resume.py Sun Jun 20 18:38:42 2010 @@ -3,10 +3,11 @@ from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue from pypy.jit.metainterp.optimizeopt import VStructValue from pypy.jit.metainterp.resume import * -from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, ConstAddr +from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.history import ConstPtr, ConstFloat from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin from pypy.jit.metainterp import executor +from pypy.jit.codewriter import heaptracker class Storage: rd_frame_info_list = None @@ -60,12 +61,12 @@ self.resboxes = [] def newframe(self, jitcode): - frame = FakeFrame(jitcode, -1, -1) + frame = FakeFrame(jitcode, -1) self.framestack.append(frame) return frame def execute_and_record(self, opnum, descr, *argboxes): - resbox = executor.execute(self.cpu, opnum, descr, *argboxes) + resbox = executor.execute(self.cpu, None, opnum, descr, *argboxes) self.trace.append((opnum, list(argboxes), resbox, @@ -74,10 +75,75 @@ self.resboxes.append(resbox) return resbox +S = lltype.GcStruct('S') +gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) +gcrefnull = lltype.nullptr(llmemory.GCREF.TO) + +class MyCPU: + class ts: + NULLREF = gcrefnull + CONST_NULL = ConstPtr(gcrefnull) + def __init__(self, values): + self.values = values + def get_latest_value_count(self): + return len(self.values) + def get_latest_value_int(self, index): + return self.values[index] + def get_latest_value_ref(self, index): + return self.values[index] + def get_latest_value_float(self, index): + return self.values[index] + +class MyBlackholeInterp: + def __init__(self, ARGS): + self.written_i = [] + self.written_r = [] + self.written_f = [] + self.ARGS = ARGS + + def get_current_position_info(self): + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + count_i = count_r = count_f = 0 + for index, ARG in enumerate(self.ARGS): + if ARG == lltype.Signed: + callback_i(index, count_i); count_i += 1 + elif ARG == llmemory.GCREF: + callback_r(index, count_r); count_r += 1 + elif ARG == lltype.Float: + callback_f(index, count_f); count_f += 1 + else: + assert 0 + return MyInfo() + + def setarg_i(self, index, value): + assert index == len(self.written_i) + self.written_i.append(value) + + def setarg_r(self, index, value): + assert index == len(self.written_r) + self.written_r.append(value) + + def setarg_f(self, index, value): + assert index == len(self.written_f) + self.written_f.append(value) + +def _next_section(reader, *expected): + bh = MyBlackholeInterp(map(lltype.typeOf, expected)) + reader.consume_one_section(bh) + expected_i = [x for x in expected if lltype.typeOf(x) == lltype.Signed] + expected_r = [x for x in expected if lltype.typeOf(x) == llmemory.GCREF] + expected_f = [x for x in expected if lltype.typeOf(x) == lltype.Float] + assert bh.written_i == expected_i + assert bh.written_r == expected_r + assert bh.written_f == expected_f + def test_simple_read(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] - c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] + #b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] + c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)] storage = Storage() storage.rd_consts = [c1, c2, c3] numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) @@ -88,44 +154,54 @@ tag(0, TAGBOX), tag(1, TAGBOX)]) storage.rd_numb = numb - - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), LLtypeMixin.cpu.ts.CONST_NULL, b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([42, gcref1, -66]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 42, 111, gcrefnull, 42, gcref1) + _next_section(reader, 222, 333) + _next_section(reader, 42, gcref1, -66) + # + metainterp = MyMetaInterp(cpu) + reader = ResumeDataBoxReader(storage, metainterp) + bi, br, bf = [None]*3, [None]*2, [None]*0 + info = MyBlackholeInterp([lltype.Signed, lltype.Signed, + llmemory.GCREF, lltype.Signed, + llmemory.GCREF]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b1s = reader.liveboxes[0] + b2s = reader.liveboxes[1] + assert bi == [b1s, ConstInt(111), b1s] + assert br == [ConstPtr(gcrefnull), b2s] + bi, br, bf = [None]*2, [None]*0, [None]*0 + info = MyBlackholeInterp([lltype.Signed, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + assert bi == [ConstInt(222), ConstInt(333)] + bi, br, bf = [None]*2, [None]*1, [None]*0 + info = MyBlackholeInterp([lltype.Signed, llmemory.GCREF, + lltype.Signed]).get_current_position_info() + reader.consume_boxes(info, bi, br, bf) + b3s = reader.liveboxes[2] + assert bi == [b1s, b3s] + assert br == [b2s] + # def test_simple_read_tagged_ints(): - b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] storage = Storage() storage.rd_consts = [] - numb = Numbering(None, [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)]) - numb = Numbering(numb, [tag(2, TAGINT), tag(3, TAGINT)]) - numb = Numbering(numb, [tag(0, TAGBOX), - tag(1, TAGINT), - tag(0, TAGBOX), - tag(1, TAGBOX)]) + numb = Numbering(None, [tag(100, TAGINT)]) storage.rd_numb = numb - b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()] - assert b1s != b3s - reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp()) - lst = reader.consume_boxes() - assert lst == [b1s, ConstInt(1), b1s, b2s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] + # + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, 100) def test_prepare_virtuals(): class FakeVinfo(object): - def allocate(self, metainterp): + def allocate(self, decoder): return "allocated" - def setfields(self, metainterp, virtual, func): + def setfields(self, decoder, virtual): assert virtual == "allocated" class FakeStorage(object): rd_virtuals = [FakeVinfo(), None] @@ -135,8 +211,8 @@ class FakeMetainterp(object): _already_allocated_resume_virtuals = None cpu = None - reader = ResumeDataReader(FakeStorage(), [], FakeMetainterp()) - assert reader.virtuals == ["allocated", None] + reader = ResumeDataDirectReader(None, FakeStorage()) + assert reader.virtuals == ["allocated", reader.virtual_default] # ____________________________________________________________ @@ -146,11 +222,13 @@ parent_resumedata_snapshot = None parent_resumedata_frame_info_list = None - def __init__(self, code, pc, exc_target, *boxes): + def __init__(self, code, pc, *boxes): self.jitcode = code self.pc = pc - self.exception_target = exc_target - self.env = list(boxes) + self._env = list(boxes) + + def get_list_of_active_boxes(self, flag): + return self._env def setup_resume_at_op(self, pc, exception_target, env): self.__init__(self.jitcode, pc, exception_target, *env) @@ -160,8 +238,7 @@ def __ne__(self, other): return self.__dict__ != other.__dict__ def __repr__(self): - return "" % (self.jitcode, self.pc, - self.exception_target, self.env) + return "" % (self.jitcode, self.pc, self._env) def test_Snapshot_create(): l = ['b0', 'b1'] @@ -176,20 +253,16 @@ def test_FrameInfo_create(): jitcode = "JITCODE" - frame = FakeFrame(jitcode, 1, 2) - fi = FrameInfo(None, frame) + fi = FrameInfo(None, jitcode, 1) assert fi.prev is None assert fi.jitcode is jitcode assert fi.pc == 1 - assert fi.exception_target == 2 jitcode1 = "JITCODE1" - frame1 = FakeFrame(jitcode, 3, 4) - fi1 = FrameInfo(fi, frame1) + fi1 = FrameInfo(fi, jitcode1, 3) assert fi1.prev is fi - assert fi1.jitcode is jitcode + assert fi1.jitcode is jitcode1 assert fi1.pc == 3 - assert fi1.exception_target == 4 def test_Numbering_create(): l = [1, 2] @@ -205,7 +278,7 @@ def test_capture_resumedata(): b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] - fs = [FakeFrame("code0", 0, -1, b1, c1, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2)] storage = Storage() capture_resumedata(fs, None, [], storage) @@ -218,13 +291,12 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) frame_info_list = storage.rd_frame_info_list @@ -235,26 +307,23 @@ assert storage.rd_snapshot.boxes == [] # for virtualrefs snapshot = storage.rd_snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env - assert snapshot.boxes is not fs[2].env + assert snapshot.boxes == fs[2]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is fs[1].parent_resumedata_frame_info_list assert frame_info_list.jitcode == 'code1' snapshot = snapshot.prev assert snapshot.prev is fs[1].parent_resumedata_snapshot - assert snapshot.boxes == fs[1].env - assert snapshot.boxes is not fs[1].env + assert snapshot.boxes == fs[1]._env frame_info_list = frame_info_list.prev assert frame_info_list.prev is None assert frame_info_list.jitcode == 'code0' snapshot = snapshot.prev assert snapshot.prev is None - assert snapshot.boxes == fs[0].env - assert snapshot.boxes is not fs[0].env + assert snapshot.boxes == fs[0]._env - fs[2].env = [b2, b3] + fs[2]._env = [b3, b2] fs[2].pc = 15 vbs = [b1, b2] vrs = [b3] @@ -266,16 +335,11 @@ assert frame_info_list.pc == 15 snapshot = storage.rd_snapshot - assert snapshot.boxes == vbs - assert snapshot.boxes is not vbs - - snapshot = snapshot.prev - assert snapshot.boxes == vrs - assert snapshot.boxes is not vrs + assert snapshot.boxes == vrs + vbs # in the same list snapshot = snapshot.prev assert snapshot.prev is fs[2].parent_resumedata_snapshot - assert snapshot.boxes == fs[2].env + assert snapshot.boxes == fs[2]._env class FakeMetaInterpStaticData: @@ -285,12 +349,13 @@ failargs_limit = 100 def test_rebuild_from_resumedata(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -300,21 +365,21 @@ b1t, b2t, b3t = [BoxInt(), BoxPtr(), BoxInt()] newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t) - result = rebuild_from_resumedata(metainterp, newboxes, storage, - False) + result = rebuild_from_resumedata(metainterp, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_with_virtualizable(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxPtr()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, [b4], [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) modifier = ResumeDataVirtualAdder(storage, memo) @@ -327,21 +392,22 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, True) assert result == ([b4t], []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards(): + py.test.skip("XXX rewrite") b1, b2, b3, b4 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -359,9 +425,9 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage, False) assert result == (None, []) - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b2, b3, b4], b1t, b2t, b3t, b4t) @@ -370,7 +436,7 @@ result = rebuild_from_resumedata(metainterp, newboxes, storage2, False) assert result == (None, []) - fs2 = fs2[:-1] + [FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = fs2[:-1] + [FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 @@ -379,6 +445,9 @@ pass fakeoptimizer = FakeOptimizer_VirtualValue() +def ConstAddr(addr, cpu): # compatibility + return ConstInt(heaptracker.adr2int(addr)) + def virtual_value(keybox, value, next): vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu), keybox) @@ -389,17 +458,18 @@ return vv def test_rebuild_from_resumedata_two_guards_w_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5 = [BoxInt(), BoxPtr(), BoxInt(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, c1, b2), - FakeFrame("code1", 3, 7, b3, c2, b1), - FakeFrame("code2", 9, -1, c3, b2)] + fs = [FakeFrame("code0", 0, b1, c1, b2), + FakeFrame("code1", 3, b3, c2, b1), + FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) storage2 = Storage() - fs = fs[:-1] + [FakeFrame("code2", 10, -1, c3, b2, b4)] + fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)] capture_resumedata(fs, None, [], storage2) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -433,9 +503,9 @@ False) b2t = metainterp.resboxes[0] - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 9, -1, c3, b2t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 9, c3, b2t)] assert metainterp.framestack == fs2 newboxes = _resume_remap(liveboxes2, [b1, b3, b4], b1t, b3t, b4t) @@ -445,17 +515,18 @@ False) b2t = metainterp.resboxes[0] assert len(metainterp.resboxes) == 2 - fs2 = [FakeFrame("code0", 0, -1, b1t, c1, b2t), - FakeFrame("code1", 3, 7, b3t, c2, b1t), - FakeFrame("code2", 10, -1, c3, b2t, b4t)] + fs2 = [FakeFrame("code0", 0, b1t, c1, b2t), + FakeFrame("code1", 3, b3t, c2, b1t), + FakeFrame("code2", 10, c3, b2t, b4t)] assert metainterp.framestack == fs2 def test_rebuild_from_resumedata_two_guards_w_shared_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3, b4, b5, b6 = [BoxPtr(), BoxPtr(), BoxInt(), BoxPtr(), BoxInt(), BoxInt()] c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), LLtypeMixin.nodebox.constbox()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, c1, b2, b3)] + fs = [FakeFrame("code0", 0, c1, b2, b3)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -467,7 +538,7 @@ tag(0, TAGCONST)] storage2 = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b4, b2)] + fs = [FakeFrame("code0", 0, b1, b4, b2)] capture_resumedata(fs, None, [], storage2) values[b4] = virtual_value(b4, b6, c4) modifier = ResumeDataVirtualAdder(storage2, memo) @@ -478,9 +549,10 @@ def test_resumedata_top_recursive_virtuals(): + py.test.skip("XXX rewrite") b1, b2, b3 = [BoxPtr(), BoxPtr(), BoxInt()] storage = Storage() - fs = [FakeFrame("code0", 0, -1, b1, b2)] + fs = [FakeFrame("code0", 0, b1, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) @@ -727,16 +799,11 @@ modifier = ResumeDataVirtualAdder(storage, memo) liveboxes = modifier.finish({}) assert storage.rd_snapshot is None - metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, [], metainterp) - lst = reader.consume_boxes() - assert lst == [b1s, b2s, b3s] - lst = reader.consume_boxes() - assert lst == [ConstInt(2), ConstInt(3)] - lst = reader.consume_boxes() - assert lst == [ConstInt(sys.maxint), ConstInt(1), ConstInt(sys.maxint), - ConstInt(2**16)] - assert metainterp.trace == [] + cpu = MyCPU([]) + reader = ResumeDataDirectReader(cpu, storage) + _next_section(reader, sys.maxint, 2**16, -65) + _next_section(reader, 2, 3) + _next_section(reader, sys.maxint, 1, sys.maxint, 2**16) def test_virtual_adder_memo_const_sharing(): @@ -756,6 +823,46 @@ assert storage2.rd_consts is memo.consts +class ResumeDataFakeReader(ResumeDataBoxReader): + """Another subclass of AbstractResumeDataReader meant for tests.""" + def __init__(self, storage, newboxes, metainterp): + self._init(metainterp.cpu, storage) + self.liveboxes = newboxes + self.metainterp = metainterp + self._prepare(storage) + + def consume_boxes(self): + self.lst = [] + class Whatever: + def __eq__(self, other): + return True + class MyInfo: + @staticmethod + def enumerate_vars(callback_i, callback_r, callback_f, _): + for index, tagged in enumerate(self.cur_numb.nums): + box = self.decode_box(tagged, Whatever()) + if box.type == INT: + callback_i(index, index) + elif box.type == REF: + callback_r(index, index) + elif box.type == FLOAT: + callback_f(index, index) + else: + assert 0 + self._prepare_next_section(MyInfo()) + return self.lst + + def write_an_int(self, count_i, box): + assert box.type == INT + self.lst.append(box) + def write_a_ref(self, count_r, box): + assert box.type == REF + self.lst.append(box) + def write_a_float(self, count_f, box): + assert box.type == FLOAT + self.lst.append(box) + + def test_virtual_adder_no_op_renaming(): b1s, b2s, b3s = [BoxInt(1), BoxInt(2), BoxInt(3)] storage = make_storage(b1s, b2s, b3s) @@ -777,7 +884,7 @@ b1t, b3t = [BoxInt(11), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b1_2, b3s], b1t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() assert lst == [b1t, b1t, b3t] lst = reader.consume_boxes() @@ -797,7 +904,7 @@ b2t, b3t = [BoxPtr(demo55o), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) lst = reader.consume_boxes() c1t = ConstInt(111) assert lst == [c1t, b2t, b3t] @@ -849,10 +956,10 @@ b5s], b3t, b5t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 2 - b2t = reader._decode_box(modifier._gettagged(b2s)) - b4t = reader._decode_box(modifier._gettagged(b4s)) + b2t = reader.decode_ref(modifier._gettagged(b2s)) + b4t = reader.decode_ref(modifier._gettagged(b4s)) trace = metainterp.trace b2new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu)], @@ -912,9 +1019,9 @@ b4t) # resume metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ (rop.NEW_ARRAY, [ConstInt(2)], b2t, LLtypeMixin.arraydescr), @@ -957,9 +1064,9 @@ # NULL = ConstPtr.value metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert len(reader.virtuals) == 1 - b2t = reader._decode_box(tag(0, TAGVIRTUAL)) + b2t = reader.decode_ref(tag(0, TAGVIRTUAL)) trace = metainterp.trace expected = [ @@ -1004,7 +1111,7 @@ newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t) metainterp = MyMetaInterp() - reader = ResumeDataReader(storage, newboxes, metainterp) + reader = ResumeDataFakeReader(storage, newboxes, metainterp) assert reader.virtuals is None trace = metainterp.trace b2set = (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_send.py Sun Jun 20 18:38:42 2010 @@ -1,7 +1,6 @@ import py from pypy.rlib.jit import JitDriver, hint, purefunction -from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rpython.ootypesystem import ootype +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -375,7 +374,7 @@ self.check_loop_count(2) def test_behavior_change_after_a_while(self): - myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + myjitdriver = JitDriver(greens = [], reds = ['y', 'x']) class Base: def __init__(self, value): self.value = value @@ -455,7 +454,7 @@ self.check_tree_loop_count(2) def test_bug1(self): - myjitdriver = JitDriver(greens = [], reds = ['node', 'n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) class Base: pass class A(Base): Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_slist.py Sun Jun 20 18:38:42 2010 @@ -1,5 +1,4 @@ import py -from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE @@ -65,7 +64,7 @@ assert res == 0 def test_getitem(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'lst', 'i']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'lst']) def f(n): lst = [] for i in range(n): Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_string.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_string.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_string.py Sun Jun 20 18:38:42 2010 @@ -1,13 +1,13 @@ import py from pypy.rlib.jit import JitDriver -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class StringTests: def test_eq_residual(self): - jitdriver = JitDriver(greens = [], reds = ['s', 'n', 'i']) + jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's']) global_s = "hello" def f(n, b, s): if b: @@ -23,7 +23,7 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 1}) + self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0}) def test_eq_folded(self): jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i']) @@ -42,10 +42,40 @@ return i res = self.meta_interp(f, [10, True, 'h'], listops=True) assert res == 5 - self.check_loops(**{self.CALL_PURE: 0}) + self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0}) + + def test_newstr(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = 'adlfkj' + chr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 + + def test_newunicode(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'm']) + def f(n, m): + while True: + jitdriver.can_enter_jit(m=m, n=n) + jitdriver.jit_merge_point(m=m, n=n) + bytecode = u'adlfkj' + unichr(n) + res = bytecode[n] + m -= 1 + if m < 0: + return ord(res) + res = self.meta_interp(f, [6, 10]) + assert res == 6 class TestOOtype(StringTests, OOJitMixin): + CALL = "oosend" CALL_PURE = "oosend_pure" class TestLLtype(StringTests, LLJitMixin): + CALL = "call" CALL_PURE = "call_pure" Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tl.py Sun Jun 20 18:38:42 2010 @@ -1,6 +1,6 @@ import py -from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import OPTIMIZER_SIMPLE +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin @@ -74,8 +74,7 @@ backendopt=True) assert res == 5040 self.check_loops({'int_mul':1, 'jump':1, - 'int_sub':1, 'int_is_true':1, 'int_le':1, - 'guard_false':1}) + 'int_sub':1, 'int_le':1, 'guard_false':1}) def test_tl_2(self): main = self._get_main() @@ -83,7 +82,7 @@ backendopt=True) assert res == main(1, 10) self.check_loops({'int_sub':1, 'int_le':1, - 'int_is_true':1, 'guard_false':1, 'jump':1}) + 'guard_false':1, 'jump':1}) def test_tl_call(self, listops=True, policy=None): from pypy.jit.tl.tl import interp Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_tlc.py Sun Jun 20 18:38:42 2010 @@ -21,7 +21,7 @@ pool = tlc.ConstantPool() bytecode = tlc.compile(src, pool) interp = self._get_interp(bytecode, pool) - return self.meta_interp(interp, [0, inputarg], view=False) + return self.meta_interp(interp, [0, inputarg]) def test_method(self): code = """ Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtual.py Sun Jun 20 18:38:42 2010 @@ -1,12 +1,12 @@ import py from pypy.rlib.jit import JitDriver, hint from pypy.rlib.objectmodel import compute_unique_id -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.ootypesystem import ootype -from pypy.jit.metainterp import heaptracker +from pypy.jit.codewriter import heaptracker class VirtualTests: def _freeze_(self): @@ -299,10 +299,9 @@ self.check_tree_loop_count(2) # the loop and the entry path # we get: # ENTER - compile the new loop - # ENTER (BlackHole) - leave # ENTER - compile the entry bridge # ENTER - compile the leaving path - self.check_enter_count(4) + self.check_enter_count(3) class VirtualMiscTests: Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py Sun Jun 20 18:38:42 2010 @@ -2,14 +2,15 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper -from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.codewriter.policy import StopAtXPolicy +from pypy.jit.codewriter import heaptracker from pypy.rlib.jit import JitDriver, hint, dont_look_inside from pypy.rlib.jit import OPTIMIZER_SIMPLE, OPTIMIZER_FULL from pypy.rlib.rarithmetic import intmask from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.rclass import FieldListAccessor from pypy.jit.metainterp.warmspot import get_stats, get_translator -from pypy.jit.metainterp import history, heaptracker +from pypy.jit.metainterp import history from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin def promote_virtualizable(*args): @@ -461,7 +462,7 @@ def test_virtualizable_with_array(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -521,7 +522,7 @@ def test_external_pass(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 'z'], + jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'], virtualizables = ['frame']) class BaseFrame(object): @@ -583,6 +584,45 @@ self.check_aborted_count(2) self.check_tree_loop_count(0) + def test_external_read_with_exception(self): + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = ['x', 'y'] + class SomewhereElse: + pass + somewhere_else = SomewhereElse() + + class FooError(Exception): + def __init__(self, value): + self.value = value + + def g(): + result = somewhere_else.top_frame.y # external read + debug_print(lltype.Void, '-+-+-+-+- external read:', result) + raise FooError(result) + + def f(n): + frame = Frame() + frame.x = n + frame.y = 10 + somewhere_else.top_frame = frame + while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) + try: + g() + except FooError, e: + frame.x -= e.value + frame.y += 1 + return frame.x + + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) + assert res == f(123) + self.check_aborted_count(2) + self.check_tree_loop_count(0) + def test_external_write(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -821,7 +861,7 @@ assert res == f(123) def test_external_read_sometimes_recursive(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'rec'], + jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -941,7 +981,7 @@ assert res == f(123) def test_promote_index_in_virtualizable_list(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1084,7 +1124,7 @@ res = self.meta_interp(f, [10]) assert res == 55 - self.check_loops(new_with_vtable=0, oois=1) + self.check_loops(new_with_vtable=0, ptr_eq=1) def test_virtual_child_frame_with_arrays(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], @@ -1196,7 +1236,7 @@ if not self.basic: py.test.skip("purely frontend test") - myjitdriver = JitDriver(greens = [], reds = ['frame', 'fail'], + myjitdriver = JitDriver(greens = [], reds = ['fail', 'frame'], virtualizables = ['frame']) class Frame(object): @@ -1251,7 +1291,7 @@ self.x = x self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) def interp(caller): @@ -1284,15 +1324,15 @@ self.n = n self.next = None - driver = JitDriver(greens=[], reds=['frame', 'result'], + driver = JitDriver(greens=[], reds=['result', 'frame'], virtualizables=['frame']) - def p(code, pc): + def p(pc, code): code = hlstr(code) return "%s %d %s" % (code, pc, code[pc]) - def c(code, pc): + def c(pc, code): return "l" not in hlstr(code) - myjitdriver = JitDriver(greens=['code', 'pc'], reds=['frame'], + myjitdriver = JitDriver(greens=['pc', 'code'], reds=['frame'], virtualizables=["frame"], get_printable_location=p, can_inline=c) def f(code, frame): Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualref.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualref.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualref.py Sun Jun 20 18:38:42 2010 @@ -12,9 +12,9 @@ class VRefTests: - def finish_metainterp_for_interp_operations(self, metainterp): - self.vrefinfo = VirtualRefInfo(metainterp.staticdata.state) - metainterp.staticdata.virtualref_info = self.vrefinfo + def finish_setup_for_interp_operations(self): + self.vrefinfo = VirtualRefInfo(self.warmrunnerstate) + self.cw.setup_vrefinfo(self.vrefinfo) def test_make_vref_simple(self): class X: @@ -81,8 +81,26 @@ JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = 1234567 # - self.metainterp.rebuild_state_after_failure(guard_op.descr, - guard_op.fail_args[:]) + # try reloading from blackhole.py's point of view + from pypy.jit.metainterp.resume import ResumeDataDirectReader + cpu = self.metainterp.cpu + cpu.get_latest_value_count = lambda : len(guard_op.fail_args) + cpu.get_latest_value_int = lambda i:guard_op.fail_args[i].getint() + cpu.get_latest_value_ref = lambda i:guard_op.fail_args[i].getref_base() + cpu.clear_latest_values = lambda count: None + resumereader = ResumeDataDirectReader(cpu, guard_op.descr) + vrefinfo = self.metainterp.staticdata.virtualref_info + lst = [] + vrefinfo.continue_tracing = lambda vref, virtual: \ + lst.append((vref, virtual)) + resumereader.consume_vref_and_vable(vrefinfo, None) + del vrefinfo.continue_tracing + assert len(lst) == 1 + lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), + lst[0][0]) # assert correct type + # + # try reloading from pyjitpl's point of view + self.metainterp.rebuild_state_after_failure(guard_op.descr) assert len(self.metainterp.framestack) == 1 assert len(self.metainterp.virtualref_boxes) == 2 assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value @@ -424,7 +442,7 @@ self.check_aborted_count(0) def test_recursive_call_1(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: pass @@ -454,7 +472,7 @@ self.check_aborted_count(0) def test_recursive_call_2(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame']) # class XY: n = 0 Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmspot.py Sun Jun 20 18:38:42 2010 @@ -277,13 +277,13 @@ type_system = 'lltype' class TestOOWarmspot(WarmspotTests, OOJitMixin): - CPUClass = runner.OOtypeCPU + ##CPUClass = runner.OOtypeCPU type_system = 'ootype' class TestWarmspotDirect(object): def setup_class(cls): from pypy.jit.metainterp.typesystem import llhelper - from pypy.jit.metainterp.support import annotate + from pypy.jit.codewriter.support import annotate from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.rpython.lltypesystem import lltype, llmemory @@ -299,7 +299,7 @@ raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally( - [BoxInt(0), BoxInt(1)]) + [0], [], [], [1], [], []) if self.no == 3: exc = lltype.malloc(OBJECT) exc.typeptr = exc_vtable @@ -308,10 +308,15 @@ lltype.cast_opaque_ptr(llmemory.GCREF, exc)) return self.no + class FakeDescr: + def as_vtable_size_descr(self): + return self + class FakeCPU(object): supports_floats = False ts = llhelper translate_support_code = False + stats = "stats" def get_fail_descr_number(self, d): return -1 @@ -320,7 +325,7 @@ pass def nodescr(self, *args, **kwds): - pass + return FakeDescr() fielddescrof = nodescr calldescrof = nodescr sizeof = nodescr @@ -343,6 +348,7 @@ return red rtyper = annotate(f, [0]) + FakeCPU.rtyper = rtyper translator = rtyper.annotator.translator translator.config.translation.gc = 'hybrid' cls.desc = WarmRunnerDesc(translator, CPUClass=FakeCPU) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_warmstate.py Sun Jun 20 18:38:42 2010 @@ -128,8 +128,7 @@ class FakeWarmRunnerDesc: cpu = FakeCPU() red_args_types = ["int", "float"] - class metainterp_sd: - virtualizable_info = None + virtualizable_info = None # state = WarmEnterState(FakeWarmRunnerDesc()) set_future_values = state.make_set_future_values() Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_ztranslation.py Sun Jun 20 18:38:42 2010 @@ -5,7 +5,6 @@ from pypy.rlib.jit import PARAMETERS, dont_look_inside from pypy.jit.metainterp.jitprof import Profiler from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.ootypesystem import ootype class TranslationTest: @@ -40,7 +39,7 @@ def can_inline(): return False - jitdriver = JitDriver(greens = [], reds = ['frame', 'total'], + jitdriver = JitDriver(greens = [], reds = ['total', 'frame'], virtualizables = ['frame'], get_jitcell_at=get_jitcell_at, set_jitcell_at=set_jitcell_at, Modified: pypy/branch/fast-forward/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/typesystem.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/typesystem.py Sun Jun 20 18:38:42 2010 @@ -4,6 +4,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker from pypy.rlib.objectmodel import r_dict def deref(T): @@ -44,9 +45,9 @@ BASETYPE = llmemory.GCREF BoxRef = history.BoxPtr ConstRef = history.ConstPtr - ConstAddr = history.ConstAddr loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstPtr(history.ConstPtr.value) + NULLREF = history.ConstPtr.value + CONST_NULL = history.ConstPtr(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -71,17 +72,16 @@ def cast_fnptr_to_root(self, fnptr): return llmemory.cast_ptr_to_adr(fnptr) - def cls_of_box(self, cpu, box): + def cls_of_box(self, box): obj = box.getref(lltype.Ptr(rclass.OBJECT)) cls = llmemory.cast_ptr_to_adr(obj.typeptr) - return history.ConstInt(cpu.cast_adr_to_int(cls)) + return history.ConstInt(heaptracker.adr2int(cls)) - def subclassOf(self, cpu, clsbox1, clsbox2): - adr = clsbox2.getaddr(cpu) + def instanceOf(self, instbox, clsbox): + adr = clsbox.getaddr() bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - adr = clsbox1.getaddr(cpu) - real_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - return rclass.ll_issubclass(real_class, bounding_class) + real_instance = instbox.getref(rclass.OBJECTPTR) + return rclass.ll_isinstance(real_instance, bounding_class) def get_exception_box(self, etype): return history.ConstInt(etype) @@ -120,7 +120,7 @@ def cast_vtable_to_hashable(self, cpu, ptr): adr = llmemory.cast_ptr_to_adr(ptr) - return cpu.cast_adr_to_int(adr) + return heaptracker.adr2int(adr) def cast_from_ref(self, TYPE, value): return lltype.cast_opaque_ptr(TYPE, value) @@ -130,8 +130,8 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): - return box.getaddr(cpu) + def getaddr_for_box(self, box): + return box.getaddr() def rd_eq(ref1, ref2): return ref1 == ref2 @@ -151,9 +151,9 @@ BASETYPE = ootype.Object BoxRef = history.BoxObj ConstRef = history.ConstObj - ConstAddr = history.ConstObj loops_done_with_this_frame_ref = None # patched by compile.py - CONST_NULL = history.ConstObj(history.ConstObj.value) + NULLREF = history.ConstObj.value + CONST_NULL = history.ConstObj(NULLREF) CVAL_NULLREF = None # patched by optimizeopt.py def new_ConstRef(self, x): @@ -233,7 +233,7 @@ return ootype.cast_to_object(value) cast_to_ref._annspecialcase_ = 'specialize:ll' - def getaddr_for_box(self, cpu, box): + def getaddr_for_box(self, box): return box.getref_base() llhelper = LLTypeHelper() Modified: pypy/branch/fast-forward/pypy/jit/metainterp/viewnode.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/viewnode.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/viewnode.py Sun Jun 20 18:38:42 2010 @@ -55,7 +55,7 @@ if isinstance(self.knownclsbox.value, int): name += str(self.knownclsbox.value) else: - name += str(self.knownclsbox.value.ptr).rpartition("_vtable")[0].rpartition('.')[2] + name += str(self.knownclsbox.value.adr.ptr).rpartition("_vtable")[0].rpartition('.')[2] elif self.structdescr: name = "Struct " + str(self.structdescr) elif self.arraydescr: Modified: pypy/branch/fast-forward/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/virtualizable.py Sun Jun 20 18:38:42 2010 @@ -11,7 +11,7 @@ class VirtualizableInfo: - TOKEN_NONE = 0 + TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 def __init__(self, warmrunnerdesc): @@ -72,6 +72,10 @@ for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] + self.static_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)]) + self.array_field_by_descrs = dict( + [(descr, i) for (i, descr) in enumerate(self.array_field_descrs)]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem @@ -102,6 +106,52 @@ i = i + 1 assert len(boxes) == i + 1 # + def write_from_resume_data_partial(virtualizable, reader, nums): + # Load values from the reader (see resume.py) described by + # the list of numbers 'nums', and write them in their proper + # place in the 'virtualizable'. This works from the end of + # the list and returns the index in 'nums' of the start of + # the virtualizable data found, allowing the caller to do + # further processing with the start of the list. + i = len(nums) - 1 + assert i >= 0 + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i]) + setarrayitem(lst, j, x) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + x = reader.load_value_of_type(FIELDTYPE, nums[i]) + setattr(virtualizable, fieldname, x) + return i + # + def load_list_of_boxes(virtualizable, reader, nums): + # Uses 'virtualizable' only to know the length of the arrays; + # does not write anything into it. The returned list is in + # the format expected of virtualizable_boxes, so it ends in + # the virtualizable itself. + i = len(nums) - 1 + assert i >= 0 + boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])] + for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: + lst = getattr(virtualizable, fieldname) + for j in range(getlength(lst)-1, -1, -1): + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i]) + boxes.append(box) + for FIELDTYPE, fieldname in unroll_static_fields_rev: + i -= 1 + assert i >= 0 + box = reader.decode_box_of_type(FIELDTYPE, nums[i]) + boxes.append(box) + boxes.reverse() + return boxes + # def check_boxes(virtualizable, boxes): # for debugging i = 0 @@ -141,8 +191,14 @@ static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) + unroll_static_fields_rev = unrolling_iterable( + reversed(list(unroll_static_fields))) + unroll_array_fields_rev = unrolling_iterable( + reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes + self.write_from_resume_data_partial = write_from_resume_data_partial + self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length @@ -172,6 +228,9 @@ return self.cpu.ts.cast_to_instance_maybe(self.VTYPEPTR, virtualizable) cast_to_vtype._annspecialcase_ = 'specialize:ll' + def cast_gcref_to_vtype(self, virtualizable): + return lltype.cast_opaque_ptr(self.VTYPEPTR, virtualizable) + def is_vtypeptr(self, TYPE): return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR) @@ -212,12 +271,6 @@ assert virtualizable.vable_token == self.TOKEN_NONE force_now._dont_inline_ = True - def forced_vable(self, virtualizable_boxes): - virtualizable_box = virtualizable_boxes[-1] - virtualizable = self.unwrap_virtualizable_box(virtualizable_box) - self.write_boxes(virtualizable, virtualizable_boxes) - virtualizable.vable_token = self.TOKEN_NONE - # ____________________________________________________________ # # The 'vable_token' field of a virtualizable is either 0, -1, or points Modified: pypy/branch/fast-forward/pypy/jit/metainterp/virtualref.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/virtualref.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/virtualref.py Sun Jun 20 18:38:42 2010 @@ -1,6 +1,7 @@ from pypy.rpython.rmodel import inputconst, log from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.jit.metainterp import history +from pypy.jit.codewriter import heaptracker class VirtualRefInfo: @@ -20,7 +21,8 @@ 'jit_virtual_ref') # build some constants adr = llmemory.cast_ptr_to_adr(self.jit_virtual_ref_vtable) - self.jit_virtual_ref_const_class = history.ConstAddr(adr, self.cpu) + adr = heaptracker.adr2int(adr) + self.jit_virtual_ref_const_class = history.ConstInt(adr) fielddescrof = self.cpu.fielddescrof self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF, 'virtual_token') @@ -60,11 +62,11 @@ # The 'virtual_token' field has the same meaning as the 'vable_token' field # of a virtualizable. It is equal to: - # * -2 (TOKEN_NONE) when tracing, except as described below; + # * -3 (TOKEN_NONE) when tracing, except as described below; # * -1 (TOKEN_TRACING_RESCALL) during tracing when we do a residual call; # * addr in the CPU stack (set by FORCE_TOKEN) when running the assembler; - # * -2 (TOKEN_NONE) after the virtual is forced, if it is forced at all. - TOKEN_NONE = -2 + # * -3 (TOKEN_NONE) after the virtual is forced, if it is forced at all. + TOKEN_NONE = -3 TOKEN_TRACING_RESCALL = -1 def virtual_ref_during_tracing(self, real_object): @@ -104,16 +106,6 @@ # marker "modified during residual call" set. return True - def forced_single_vref(self, gcref, real_object): - if not self.is_virtual_ref(gcref): - return - assert real_object - vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) - assert (vref.virtual_token != self.TOKEN_NONE and - vref.virtual_token != self.TOKEN_TRACING_RESCALL) - vref.virtual_token = self.TOKEN_NONE - vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) - def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return Modified: pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py Sun Jun 20 18:38:42 2010 @@ -16,12 +16,13 @@ from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.unsimplify import call_final_function -from pypy.jit.metainterp import codewriter -from pypy.jit.metainterp import support, history, pyjitpl, gc +from pypy.jit.metainterp import history, pyjitpl, gc from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp -from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler +from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.codewriter import support, codewriter +from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE # ____________________________________________________________ @@ -130,9 +131,6 @@ stats.maybe_view() stats.check_consistency() -class JitException(Exception): - _go_through_llinterp_uncaught_ = True # ugh - class ContinueRunningNormallyBase(JitException): pass @@ -144,47 +142,49 @@ class WarmRunnerDesc(object): def __init__(self, translator, policy=None, backendopt=True, CPUClass=None, - optimizer=None, **kwds): + optimizer=None, ProfilerClass=EmptyProfiler, **kwds): pyjitpl._warmrunnerdesc = self # this is a global for debugging only! - if policy is None: - policy = JitPolicy() self.set_translator(translator) + self.build_cpu(CPUClass, **kwds) self.find_portal() - self.codewriter = codewriter.CodeWriter(self.rtyper) - graphs = self.codewriter.find_all_graphs(self.portal_graph, - policy, - CPUClass.supports_floats) + self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + if policy is None: + policy = JitPolicy() + policy.set_supports_floats(self.cpu.supports_floats) + graphs = self.codewriter.find_all_graphs(policy) policy.dump_unsafe_loops() self.check_access_directly_sanity(graphs) if backendopt: self.prejit_optimizations(policy, graphs) - self.build_meta_interp(CPUClass, **kwds) + self.build_meta_interp(ProfilerClass) self.make_args_specification() # from pypy.jit.metainterp.virtualref import VirtualRefInfo - self.metainterp_sd.virtualref_info = VirtualRefInfo(self) + vrefinfo = VirtualRefInfo(self) + self.codewriter.setup_vrefinfo(vrefinfo) if self.jitdriver.virtualizables: from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.metainterp_sd.virtualizable_info = VirtualizableInfo(self) + self.virtualizable_info = VirtualizableInfo(self) + self.codewriter.setup_virtualizable_info(self.virtualizable_info) + else: + self.virtualizable_info = None # self.make_exception_classes() self.make_driverhook_graphs() self.make_enter_function() self.rewrite_jit_merge_point(policy) - - self.codewriter.generate_bytecode(self.metainterp_sd, - self.portal_graph, - self.portal_runner_ptr - ) + + verbose = not self.cpu.translate_support_code + self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jit() self.rewrite_set_param() - self.rewrite_force_virtual() + self.rewrite_force_virtual(vrefinfo) self.add_finish() - self.metainterp_sd.finish_setup(optimizer=optimizer) + self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info if vinfo is not None: vinfo.finish() if self.cpu.translate_support_code: @@ -244,11 +244,10 @@ remove_asserts=True, really_remove_asserts=True) - def build_meta_interp(self, CPUClass, translate_support_code=False, - view="auto", no_stats=False, - ProfilerClass=EmptyProfiler, **kwds): + def build_cpu(self, CPUClass, translate_support_code=False, + no_stats=False, **kwds): assert CPUClass is not None - opt = history.Options(**kwds) + self.opt = history.Options(**kwds) if no_stats: stats = history.NoStats() else: @@ -259,18 +258,18 @@ annhelper = self.annhelper else: annhelper = None - cpu = CPUClass(self.translator.rtyper, self.stats, opt, + cpu = CPUClass(self.translator.rtyper, self.stats, self.opt, translate_support_code, gcdescr=self.gcdescr) self.cpu = cpu - self.metainterp_sd = MetaInterpStaticData(self.portal_graph, # xxx - cpu, - self.stats, opt, + + def build_meta_interp(self, ProfilerClass): + self.metainterp_sd = MetaInterpStaticData(self.cpu, + self.opt, ProfilerClass=ProfilerClass, warmrunnerdesc=self) def make_exception_classes(self): - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(self.PORTAL_FUNCTYPE.ARGS)]) + class DoneWithThisFrameVoid(JitException): def __str__(self): return 'DoneWithThisFrameVoid()' @@ -304,18 +303,19 @@ return 'ExitFrameWithExceptionRef(%s)' % (self.value,) class ContinueRunningNormally(ContinueRunningNormallyBase): - def __init__(self, argboxes): - # accepts boxes as argument, but unpacks them immediately - # before we raise the exception -- the boxes' values will - # be modified in a 'finally' by restore_patched_boxes(). - from pypy.jit.metainterp.warmstate import unwrap - for i, name, ARG in portalfunc_ARGS: - v = unwrap(ARG, argboxes[i]) - setattr(self, name, v) - + def __init__(self, gi, gr, gf, ri, rr, rf): + # the six arguments are: lists of green ints, greens refs, + # green floats, red ints, red refs, and red floats. + self.green_int = gi + self.green_ref = gr + self.green_float = gf + self.red_int = ri + self.red_ref = rr + self.red_float = rf def __str__(self): - return 'ContinueRunningNormally(%s)' % ( - ', '.join(map(str, self.args)),) + return 'ContinueRunningNormally(%s, %s, %s, %s, %s, %s)' % ( + self.green_int, self.green_ref, self.green_float, + self.red_int, self.red_ref, self.red_float) self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt @@ -411,17 +411,10 @@ def make_args_specification(self): graph, block, index = self.jit_merge_point_pos op = block.operations[index] - args = op.args[2:] - ALLARGS = [] - self.green_args_spec = [] - self.red_args_types = [] - for i, v in enumerate(args): - TYPE = v.concretetype - ALLARGS.append(TYPE) - if i < len(self.jitdriver.greens): - self.green_args_spec.append(TYPE) - else: - self.red_args_types.append(history.getkind(TYPE)) + greens_v, reds_v = support.decode_hp_hint_args(op) + ALLARGS = [v.concretetype for v in (greens_v + reds_v)] + self.green_args_spec = [v.concretetype for v in greens_v] + self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] self.num_green_args = len(self.green_args_spec) RESTYPE = graph.getreturnvar().concretetype (self.JIT_ENTER_FUNCTYPE, @@ -443,7 +436,7 @@ continue op = block.operations[index] - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) args_v = greens_v + reds_v vlist = [Constant(jit_enter_fnptr, FUNCPTR)] + args_v @@ -500,13 +493,24 @@ # ____________________________________________________________ # Prepare the portal_runner() helper # + from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) self.portal_ptr = portal_ptr - portalfunc_ARGS = unrolling_iterable( - [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)]) - - + # + portalfunc_ARGS = [] + nums = {} + for i, ARG in enumerate(PORTALFUNC.ARGS): + if i < len(self.jitdriver.greens): + color = 'green' + else: + color = 'red' + attrname = '%s_%s' % (color, history.getkind(ARG)) + count = nums.get(attrname, 0) + nums[attrname] = count + 1 + portalfunc_ARGS.append((ARG, attrname, count)) + portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS) + # rtyper = self.translator.rtyper RESULT = PORTALFUNC.RESULT result_kind = history.getkind(RESULT) @@ -520,21 +524,22 @@ portal_ptr)(*args) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -550,8 +555,9 @@ self.PTR_PORTAL_FUNCTYPE.TO, self.PTR_PORTAL_FUNCTYPE.TO.ARGS, self.PTR_PORTAL_FUNCTYPE.TO.RESULT) + self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) - vinfo = self.metainterp_sd.virtualizable_info + vinfo = self.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) @@ -565,22 +571,23 @@ fail_descr = self.cpu.execute_token(loop_token) except self.ContinueRunningNormally, e: args = () - for _, name, _ in portalfunc_ARGS: - v = getattr(e, name) - args = args + (v,) + for ARGTYPE, attrname, count in portalfunc_ARGS: + x = getattr(e, attrname)[count] + x = specialize_value(ARGTYPE, x) + args = args + (x,) return ll_portal_runner(*args) except self.DoneWithThisFrameVoid: assert result_kind == 'void' return except self.DoneWithThisFrameInt, e: assert result_kind == 'int' - return lltype.cast_primitive(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameRef, e: assert result_kind == 'ref' - return ts.cast_from_ref(RESULT, e.result) + return specialize_value(RESULT, e.result) except self.DoneWithThisFrameFloat, e: assert result_kind == 'float' - return e.result + return specialize_value(RESULT, e.result) except self.ExitFrameWithExceptionRef, e: value = ts.cast_to_baseclass(e.value) if not we_are_translated(): @@ -597,8 +604,10 @@ if vinfo is not None: self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - self.num_green_args) + self.cpu.vable_token_descr = vinfo.vable_token_descr else: self.cpu.index_of_virtualizable = -1 + self.cpu.vable_token_descr = None # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr @@ -607,7 +616,7 @@ op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' - greens_v, reds_v = decode_hp_hint_args(op) + greens_v, reds_v = support.decode_hp_hint_args(op) vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v @@ -651,22 +660,8 @@ op.opname = 'direct_call' op.args[:3] = [closures[funcname]] - def rewrite_force_virtual(self): + def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': py.test.skip("rewrite_force_virtual: port it to ootype") all_graphs = self.translator.graphs - vrefinfo = self.metainterp_sd.virtualref_info vrefinfo.replace_force_virtual_with_call(all_graphs) - - -def decode_hp_hint_args(op): - # Returns (list-of-green-vars, list-of-red-vars) without Voids. - assert op.opname == 'jit_marker' - jitdriver = op.args[1].value - numgreens = len(jitdriver.greens) - numreds = len(jitdriver.reds) - greens_v = op.args[2:2+numgreens] - reds_v = op.args[2+numgreens:] - assert len(reds_v) == numreds - return ([v for v in greens_v if v.concretetype is not lltype.Void], - [v for v in reds_v if v.concretetype is not lltype.Void]) Modified: pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py (original) +++ pypy/branch/fast-forward/pypy/jit/metainterp/warmstate.py Sun Jun 20 18:38:42 2010 @@ -11,11 +11,26 @@ from pypy.rlib.jit import DEBUG_PROFILE from pypy.rlib.jit import BaseJitCell from pypy.rlib.debug import debug_start, debug_stop, debug_print -from pypy.jit.metainterp import support, history +from pypy.jit.metainterp import history +from pypy.jit.codewriter import support, heaptracker # ____________________________________________________________ @specialize.arg(0) +def specialize_value(TYPE, x): + """'x' must be a Signed, a GCREF or a Float. + This function casts it to a more specialized type, like Char or Ptr(..). + """ + INPUT = lltype.typeOf(x) + if INPUT is lltype.Signed: + return lltype.cast_primitive(TYPE, x) # XXX missing: Ptr(non-gc) + elif INPUT is lltype.Float: + assert TYPE is lltype.Float + return x + else: + return lltype.cast_opaque_ptr(TYPE, x) + + at specialize.arg(0) def unwrap(TYPE, box): if TYPE is lltype.Void: return None @@ -39,7 +54,7 @@ return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) - value = cpu.cast_adr_to_int(adr) + value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) @@ -180,7 +195,7 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = metainterp_sd.virtualizable_info + vinfo = self.warmrunnerdesc.virtualizable_info num_green_args = self.warmrunnerdesc.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() @@ -401,7 +416,7 @@ warmrunnerdesc = self.warmrunnerdesc cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.metainterp_sd.virtualizable_info + vinfo = warmrunnerdesc.virtualizable_info red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) # def set_future_values(*redargs): Modified: pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py Sun Jun 20 18:38:42 2010 @@ -24,7 +24,7 @@ unrolling_compare_dispatch_table = unrolling_iterable( enumerate(compare_ops)) -jitdriver = JitDriver(greens = ['code', 'instr_index'], +jitdriver = JitDriver(greens = ['instr_index', 'code'], reds = ['frame'], virtualizables = ['frame']) Modified: pypy/branch/fast-forward/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/tl.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/tl.py Sun Jun 20 18:38:42 2010 @@ -56,7 +56,7 @@ def make_interp(supports_call): myjitdriver = JitDriver(greens = ['pc', 'code'], - reds = ['stack', 'inputarg'], + reds = ['inputarg', 'stack'], virtualizables = ['stack']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): Modified: pypy/branch/fast-forward/pypy/jit/tl/tla/targettla.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/tla/targettla.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/tla/targettla.py Sun Jun 20 18:38:42 2010 @@ -28,7 +28,7 @@ def target(driver, args): return entry_point, None -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/branch/fast-forward/pypy/jit/tl/tla/tla.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/tla/tla.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/tla/tla.py Sun Jun 20 18:38:42 2010 @@ -71,10 +71,10 @@ # ____________________________________________________________ -def get_printable_location(bytecode, pc): +def get_printable_location(pc, bytecode): return str(pc) -jitdriver = JitDriver(greens=['bytecode', 'pc'], +jitdriver = JitDriver(greens=['pc', 'bytecode'], reds=['self'], virtualizables=['self'], get_printable_location=get_printable_location) Modified: pypy/branch/fast-forward/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/tlc.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/tlc.py Sun Jun 20 18:38:42 2010 @@ -226,7 +226,7 @@ def make_interp(supports_call, jitted=True): - myjitdriver = JitDriver(greens = ['code', 'pc'], + myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['frame', 'pool']) def interp(code='', pc=0, inputarg=0, pool=None): Modified: pypy/branch/fast-forward/pypy/jit/tl/tlr.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/tlr.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/tlr.py Sun Jun 20 18:38:42 2010 @@ -12,7 +12,7 @@ NEG_A = 8 class TLRJitDriver(JitDriver): - greens = ['bytecode', 'pc'] + greens = ['pc', 'bytecode'] reds = ['a', 'regs'] tlrjitdriver = TLRJitDriver() Modified: pypy/branch/fast-forward/pypy/jit/tool/jitoutput.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tool/jitoutput.py (original) +++ pypy/branch/fast-forward/pypy/jit/tool/jitoutput.py Sun Jun 20 18:38:42 2010 @@ -15,14 +15,9 @@ '^Blackhole:\s+([\d.]+)$'), (None, '^TOTAL.*$'), (('ops.total',), '^ops:\s+(\d+)$'), - (('ops.calls',), '^\s+calls:\s+(\d+)$'), - (('ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('recorded_ops.total',), '^recorded ops:\s+(\d+)$'), (('recorded_ops.calls',), '^\s+calls:\s+(\d+)$'), - (('recorded_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('guards',), '^guards:\s+(\d+)$'), - (('blackholed_ops.total',), '^blackholed ops:\s+(\d+)$'), - (('blackholed_ops.pure_calls',), '^\s+pure calls:\s+(\d+)$'), (('opt_ops',), '^opt ops:\s+(\d+)$'), (('opt_guards',), '^opt guards:\s+(\d+)$'), (('forcings',), '^forcings:\s+(\d+)$'), @@ -36,8 +31,9 @@ class Ops(object): total = 0 + +class RecordedOps(Ops): calls = 0 - pure_calls = 0 class Aborts(object): trace_too_long = 0 @@ -61,8 +57,7 @@ def __init__(self): self.ops = Ops() - self.recorded_ops = Ops() - self.blackholed_ops = Ops() + self.recorded_ops = RecordedOps() self.abort = Aborts() def parse_prof(output): Modified: pypy/branch/fast-forward/pypy/jit/tool/test/test_jitoutput.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tool/test/test_jitoutput.py (original) +++ pypy/branch/fast-forward/pypy/jit/tool/test/test_jitoutput.py Sun Jun 20 18:38:42 2010 @@ -35,14 +35,9 @@ assert info.blackhole_no == 1 assert info.backend_no == 1 assert info.ops.total == 2 - assert info.ops.calls == 0 - assert info.ops.pure_calls == 0 assert info.recorded_ops.total == 2 assert info.recorded_ops.calls == 0 - assert info.recorded_ops.pure_calls == 0 assert info.guards == 1 - assert info.blackholed_ops.total == 0 - assert info.blackholed_ops.pure_calls == 0 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 0 @@ -53,14 +48,9 @@ Blackhole: 1 TOTAL: 0.025532 ops: 2 - calls: 1 - pure calls: 1 recorded ops: 6 calls: 3 - pure calls: 2 guards: 1 -blackholed ops: 5 - pure calls: 3 opt ops: 6 opt guards: 1 forcings: 1 @@ -81,14 +71,9 @@ assert info.backend_no == 1 assert info.backend_time == 0.000525 assert info.ops.total == 2 - assert info.ops.calls == 1 - assert info.ops.pure_calls == 1 assert info.recorded_ops.total == 6 assert info.recorded_ops.calls == 3 - assert info.recorded_ops.pure_calls == 2 assert info.guards == 1 - assert info.blackholed_ops.total == 5 - assert info.blackholed_ops.pure_calls == 3 assert info.opt_ops == 6 assert info.opt_guards == 1 assert info.forcings == 1 Modified: pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_functions.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_functions.py (original) +++ pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_functions.py Sun Jun 20 18:38:42 2010 @@ -210,14 +210,14 @@ result = f(byref(c_int(99))) assert not result.contents == 99 - def test_errors(self): + def test_errors_1(self): f = dll._testfunc_p_p f.restype = c_int class X(Structure): _fields_ = [("y", c_int)] - raises(TypeError, f, X()) #cannot convert parameter + raises(ArgumentError, f, X()) #cannot convert parameter ################################################################ def test_shorts(self): @@ -305,7 +305,7 @@ assert 13577625587 == f(1000000000000, cb) - def test_errors(self): + def test_errors_2(self): raises(AttributeError, getattr, dll, "_xxx_yyy") raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") Modified: pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_unicode.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_unicode.py (original) +++ pypy/branch/fast-forward/pypy/lib/app_test/ctypes_tests/test_unicode.py Sun Jun 20 18:38:42 2010 @@ -90,7 +90,7 @@ assert func(u"abc") == "abc" assert func(u"????") == "" - def test_ascii_replace(self): + def test_ascii_replace_2(self): ctypes.set_conversion_mode("ascii", "replace") assert func("abc") == "abc" assert func(u"abc") == "abc" Modified: pypy/branch/fast-forward/pypy/lib/app_test/test_functools.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/app_test/test_functools.py (original) +++ pypy/branch/fast-forward/pypy/lib/app_test/test_functools.py Sun Jun 20 18:38:42 2010 @@ -31,7 +31,7 @@ p = self.thetype(map, lambda x: x*10) assert p([1,2,3,4]) == [10, 20, 30, 40] - def test_attributes(self): + def test_attributes_1(self): p = self.thetype(capture, 1, 2, a=10, b=20) # attributes should be readable assert p.func == capture @@ -118,7 +118,7 @@ py.test.raises(ZeroDivisionError, self.thetype(f), 1, 0) py.test.raises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): + def test_attributes_2(self): p = self.thetype(hex) try: del p.__dict__ Modified: pypy/branch/fast-forward/pypy/lib/datetime.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/datetime.py (original) +++ pypy/branch/fast-forward/pypy/lib/datetime.py Sun Jun 20 18:38:42 2010 @@ -1524,7 +1524,7 @@ # Convert self to UTC, and attach the new time zone object. myoffset = self.utcoffset() if myoffset is None: - raise ValuError("astimezone() requires an aware datetime") + raise ValueError("astimezone() requires an aware datetime") utc = (self - myoffset).replace(tzinfo=tz) # Convert from UTC to tz's local time. Modified: pypy/branch/fast-forward/pypy/lib/dbm.py ============================================================================== --- pypy/branch/fast-forward/pypy/lib/dbm.py (original) +++ pypy/branch/fast-forward/pypy/lib/dbm.py Sun Jun 20 18:38:42 2010 @@ -1,4 +1,4 @@ -from ctypes import * +from ctypes import Structure, c_char_p, c_int, c_void_p, CDLL import ctypes.util import os, sys @@ -15,6 +15,11 @@ ('dsize', c_int), ] + def __init__(self, text): + if not isinstance(text, str): + raise TypeError("datum: expected string, not %s" % type(text)) + Structure.__init__(self, text, len(text)) + class dbm(object): def __init__(self, dbmobj): self._aobj = dbmobj @@ -42,9 +47,7 @@ def get(self, key, default=None): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] @@ -65,12 +68,8 @@ def __setitem__(self, key, value): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) - data = datum() - data.dptr = c_char_p(value) - data.dsize = c_int(len(value)) + dat = datum(key) + data = datum(value) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_REPLACE) if getattr(lib, funcs['error'])(self._aobj): getattr(lib, funcs['clearerr'])(self._aobj) @@ -80,15 +79,11 @@ def setdefault(self, key, default=''): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] - data = datum() - data.dptr = c_char_p(default) - data.dsize = c_int(len(default)) + data = datum(default) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_INSERT) if status < 0: getattr(lib, funcs['clearerr'])(self._aobj) @@ -98,9 +93,7 @@ def has_key(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return True @@ -109,9 +102,7 @@ def __delitem__(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) status = getattr(lib, funcs['delete'])(self._aobj, dat) if status < 0: raise KeyError(key) @@ -146,7 +137,7 @@ library = "GNU gdbm" funcs = {} -_init_func('open', [c_char_p, c_int, c_int]) +_init_func('open', (c_char_p, c_int, c_int)) _init_func('close', restype=c_void_p) _init_func('firstkey', restype=datum) _init_func('nextkey', restype=datum) @@ -160,6 +151,9 @@ def open(filename, flag='r', mode=0666): "open a DBM database" + if not isinstance(filename, str): + raise TypeError("expected string") + openflag = 0 try: @@ -177,3 +171,6 @@ if a_db == 0: raise error("Could not open file %s.db" % filename) return dbm(a_db) + +__all__ = ('datum', 'dbm', 'error', 'funcs', 'open', 'library') + Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Sun Jun 20 18:38:42 2010 @@ -187,13 +187,15 @@ cont = False args_w = [space.w_None] * num_iterators for i in range(num_iterators): - try: - args_w[i] = space.next(iterators_w[i]) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - else: - cont = True + if iterators_w[i] is not None: + try: + args_w[i] = space.next(iterators_w[i]) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + iterators_w[i] = None + else: + cont = True if cont: w_args = space.newtuple(args_w) if none_func: Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py Sun Jun 20 18:38:42 2010 @@ -477,7 +477,7 @@ assert a is a1 assert a.l == [1, 2] - def test_cmp(self): + def test_cmp_and_coerce(self): class A: def __coerce__(self, other): return (1, 2) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_functional.py Sun Jun 20 18:38:42 2010 @@ -48,16 +48,35 @@ b = [ 2, 3, 4, 5, 6] assert map(None, a, b) == [('1', 2), (2, 3), (3, 4), ('b', 5), (None, 6)] - def test_map_multiply(self): + def test_map_add(self): a = [1, 2, 3, 4] b = [0, 1, 1, 1] - assert map(lambda x, y: x+y, a, b) == [1, 2, 4, 5] + assert map(lambda x, y: x+y, a, b) == [1, 3, 4, 5] - def test_map_multiply(self): + def test_map_first_item(self): a = [1, 2, 3, 4, 5] b = [] assert map(lambda x, y: x, a, b) == a + def test_map_iterables(self): + class A(object): + def __init__(self, n): + self.n = n + def __iter__(self): + return B(self.n) + class B(object): + def __init__(self, n): + self.n = n + def next(self): + self.n -= 1 + if self.n == 0: raise StopIteration + return self.n + result = map(None, A(3), A(8)) + # this also checks that B.next() is not called any more after it + # raised StopIteration once + assert result == [(2, 7), (1, 6), (None, 5), (None, 4), + (None, 3), (None, 2), (None, 1)] + class AppTestZip: def test_one_list(self): assert zip([1,2,3]) == [(1,), (2,), (3,)] Modified: pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py Sun Jun 20 18:38:42 2010 @@ -39,8 +39,6 @@ # XXX move some of these functions to RPython (like charmap_encode, # charmap_build) to make them faster -import sys - def escape_encode( obj, errors='strict'): """None """ @@ -84,36 +82,36 @@ res = ''.join(res) return res, len(res) -if sys.maxunicode == 65535: - unicode_bytes = 2 -else: - unicode_bytes = 4 - def unicode_internal_encode( obj, errors='strict'): """None """ - if type(obj) == unicode: - p = [] - t = [ord(x) for x in obj] - for i in t: - bytes = [] - for j in xrange(unicode_bytes): - bytes += chr(i%256) - i >>= 8 - if sys.byteorder == "big": - bytes.reverse() - p += bytes - res = ''.join(p) - return res, len(res) + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 else: - res = "You can do better than this" # XXX make this right - return res, len(res) + unicode_bytes = 4 + p = [] + for x in obj: + i = ord(x) + bytes = [] + for j in xrange(unicode_bytes): + bytes += chr(i%256) + i >>= 8 + if sys.byteorder == "big": + bytes.reverse() + p += bytes + res = ''.join(p) + return res, len(res) def unicode_internal_decode( unistr, errors='strict'): - import sys if type(unistr) == unicode: return unistr, len(unistr) else: + import sys + if sys.maxunicode == 65535: + unicode_bytes = 2 + else: + unicode_bytes = 4 p = [] i = 0 if sys.byteorder == "big": @@ -541,6 +539,7 @@ hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10, 16)] def hexescape(s, pos, digits, message, errors): + import sys chr = 0 p = [] if (pos+digits>len(s)): @@ -580,6 +579,7 @@ return res, pos def PyUnicode_DecodeUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' @@ -762,6 +762,7 @@ def PyUnicode_DecodeRawUnicodeEscape(s, size, errors): + import sys if (size == 0): return u'' Modified: pypy/branch/fast-forward/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/fast-forward/pypy/module/_codecs/test/test_codecs.py Sun Jun 20 18:38:42 2010 @@ -84,7 +84,7 @@ assert str(UnicodeTranslateError( u"g\uffffrk", 1, 2, "ouch"))== "can't translate character u'\\uffff' in position 1: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeTranslateError( u"g\U00010000rk", 1, 2, "ouch"))== "can't translate character u'\\U00010000' in position 1: ouch" @@ -107,7 +107,7 @@ assert str(UnicodeEncodeError( "ascii", u"\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\uffff' in position 0: ouch" - if sys.maxunicode > 0xffff: + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", u"\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" @@ -229,7 +229,9 @@ def test_unicode_internal_encode(self): import sys - enc = u"a".encode("unicode_internal") + class U(unicode): + pass + enc = U(u"a").encode("unicode_internal") if sys.maxunicode == 65535: # UCS2 build if sys.byteorder == "big": assert enc == "\x00a" @@ -373,7 +375,7 @@ decoded = _codecs.unicode_escape_decode(s)[0] assert decoded == '' - def test_charmap_decode(self): + def test_charmap_decode_1(self): import codecs res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab") assert res == (u"ab\ufffd", 3) @@ -525,7 +527,7 @@ def test_charmap_encode(self): assert 'xxx'.encode('charmap') == 'xxx' - def test_charmap_decode(self): + def test_charmap_decode_2(self): assert 'foo'.decode('charmap') == 'foo' def test_utf7_start_end_in_exception(self): Modified: pypy/branch/fast-forward/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/branch/fast-forward/pypy/module/_file/test/test_file_extra.py Sun Jun 20 18:38:42 2010 @@ -71,12 +71,6 @@ inputlines = list(self.file) assert inputlines == self.expected_lines - def test_repr(self): - r = repr(self.file) - assert r.find('open file') >= 0 - assert r.find(self.file.name) >= 0 - assert r.find(self.file.mode) >= 0 - def test_isatty(self): assert not self.file.isatty() Modified: pypy/branch/fast-forward/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_rawffi/array.py (original) +++ pypy/branch/fast-forward/pypy/module/_rawffi/array.py Sun Jun 20 18:38:42 2010 @@ -8,7 +8,7 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror +from pypy.interpreter.error import OperationError from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value Modified: pypy/branch/fast-forward/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/fast-forward/pypy/module/_rawffi/structure.py Sun Jun 20 18:38:42 2010 @@ -9,7 +9,7 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.interpreter.error import OperationError, wrap_oserror, operationerrfmt +from pypy.interpreter.error import OperationError, operationerrfmt from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value Modified: pypy/branch/fast-forward/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/fast-forward/pypy/module/_rawffi/test/test__rawffi.py Sun Jun 20 18:38:42 2010 @@ -160,6 +160,17 @@ { return 42; } + + typedef union { + short x; + long y; + } UN; + + UN ret_un_func(UN inp) + { + inp.y = inp.x * 100; + return inp; + } ''')) symbols = """get_char char_check get_raw_pointer @@ -928,6 +939,17 @@ assert a[3] == 'z' assert a[4] == 't' + def test_union(self): + skip("segfaulting") + import _rawffi + longsize = _rawffi.sizeof('l') + S = _rawffi.Structure((longsize, longsize)) + s = S(autofree=False) + lib = _rawffi.CDLL(self.lib_name) + f = lib.ptr('ret_un_func', [(S, 1)], (S, 1)) + ret = f(s) + s.free() + class AppTestAutoFree: def setup_class(cls): space = gettestobjspace(usemodules=('_rawffi', 'struct')) Modified: pypy/branch/fast-forward/pypy/module/cpyext/TODO ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/TODO (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/TODO Sun Jun 20 18:38:42 2010 @@ -15,8 +15,6 @@ - Fix GIL handling (e.g. after releasing the GIL, GC operations might occur in savethreads). - - Export pointers where pointers are expected, i.e. kill the "#define PyExc_OSError &PyExc_OSError" hack. - - refactor management of py_objects_r2w and py_objects_w2r, this can probably be expressed in terms of _PyObject_GC_TRACK macros. Modified: pypy/branch/fast-forward/pypy/module/cpyext/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/__init__.py Sun Jun 20 18:38:42 2010 @@ -64,7 +64,7 @@ import pypy.module.cpyext.sliceobject import pypy.module.cpyext.stubsactive import pypy.module.cpyext.pystate -import pypy.module.cpyext.datetime +import pypy.module.cpyext.cdatetime import pypy.module.cpyext.complexobject import pypy.module.cpyext.weakrefobject import pypy.module.cpyext.funcobject Modified: pypy/branch/fast-forward/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/api.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/api.py Sun Jun 20 18:38:42 2010 @@ -181,7 +181,7 @@ """ if error is _NOT_SPECIFIED: if restype is PyObject: - error = lltype.nullptr(PyObject.TO) + error = lltype.nullptr(restype.TO) elif restype is lltype.Void: error = CANNOT_FAIL if type(error) is int: @@ -251,7 +251,7 @@ raise state = space.fromcache(State) state.set_exception(e) - if restype is PyObject: + if is_PyObject(restype): return None else: return api_function.error_value @@ -315,6 +315,7 @@ '_Py_TrueStruct#': ('PyObject*', 'space.w_True'), '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'), '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'), + 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'None'), } FORWARD_DECLS = [] INIT_FUNCTIONS = [] @@ -360,7 +361,9 @@ def get_structtype_for_ctype(ctype): from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr - return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr}[ctype] + from pypy.module.cpyext.cdatetime import PyDateTime_CAPI + return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr, + "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype] PyTypeObject = lltype.ForwardReference() PyTypeObjectPtr = lltype.Ptr(PyTypeObject) @@ -470,9 +473,9 @@ assert len(args) == len(callable.api_func.argtypes) for i, (typ, is_wrapped) in argtypes_enum_ui: arg = args[i] - if typ is PyObject and is_wrapped: + if is_PyObject(typ) and is_wrapped: if arg: - arg_conv = from_ref(space, arg) + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) else: arg_conv = None else: @@ -506,13 +509,14 @@ % (callable.__name__,)) retval = error_value - elif callable.api_func.restype is PyObject: + elif is_PyObject(callable.api_func.restype): if result is None: retval = make_ref(space, None) elif isinstance(result, BorrowPair): retval = result.get_ref(space) elif not rffi._isllptr(result): - retval = make_ref(space, result) + retval = rffi.cast(callable.api_func.restype, + make_ref(space, result)) else: retval = result elif callable.api_func.restype is not lltype.Void: @@ -612,8 +616,10 @@ for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue - if name.startswith('PyExc_'): - global_objects.append('%s %s;' % (typ[:-1], '_' + name)) + if typ == 'PyDateTime_CAPI*': + continue + elif name.startswith('PyExc_'): + global_objects.append('%s _%s;' % (typ[:-1], name)) else: global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) @@ -653,7 +659,13 @@ name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) - ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)), + if typ == 'PyObject*': + value = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + value = w_obj + else: + assert False, "Unknown static pointer: %s %s" % (typ, name) + ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_'): @@ -724,6 +736,7 @@ ("SIZEOF_INT", rffi.INT) ]: pypy_macros.append("#define %s %s" % (macro_name, rffi.sizeof(size))) + pypy_macros.append('') pypy_macros_h = udir.join('pypy_macros.h') pypy_macros_h.write('\n'.join(pypy_macros)) @@ -789,7 +802,7 @@ if sys.platform == "win32": # '%s' undefined; assuming extern returning int compile_extra.append("/we4013") - else: + elif sys.platform == 'linux2': compile_extra.append("-Werror=implicit-function-declaration") export_symbols_eci.append('pypyAPI') else: @@ -804,6 +817,8 @@ elif name.startswith('PyExc_'): structs.append('extern PyTypeObject _%s;' % (name,)) structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) + elif typ == 'PyDateTime_CAPI*': + structs.append('%s %s = NULL;' % (typ, name)) struct_file.write('\n'.join(structs)) eci = ExternalCompilationInfo( @@ -853,7 +868,12 @@ name = '_' + name from pypy.module import cpyext w_obj = eval(expr) - struct_ptr = make_ref(space, w_obj) + if typ in ('PyObject*', 'PyTypeObject*'): + struct_ptr = make_ref(space, w_obj) + elif typ == 'PyDateTime_CAPI*': + continue + else: + assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) @@ -946,7 +966,7 @@ assert len(args) == len(FT.ARGS) for i, ARG in unrolling_arg_types: arg = args[i] - if ARG is PyObject: + if is_PyObject(ARG): if arg is None: boxed_args += (lltype.nullptr(PyObject.TO),) elif isinstance(arg, W_Root): @@ -969,7 +989,7 @@ finally: state.swap_borrow_container(old_container) - if RESULT_TYPE is PyObject: + if is_PyObject(RESULT_TYPE): if result is None: ret = result elif isinstance(result, W_Root): Modified: pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/include/Python.h Sun Jun 20 18:38:42 2010 @@ -15,7 +15,12 @@ #else # define MS_WIN32 1 # define MS_WINDOWS 1 -# include +# ifdef _MSC_VER +# include +# endif +# ifdef __MINGW32__ +# include +# endif # include # define Py_DEPRECATED(VERSION_UNUSED) # ifdef Py_BUILD_CORE @@ -104,6 +109,8 @@ #include +#include "modsupport.inl" + /* Define macros for inline documentation. */ #define PyDoc_VAR(name) static char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) Modified: pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/include/datetime.h Sun Jun 20 18:38:42 2010 @@ -4,7 +4,21 @@ extern "C" { #endif -#define PyDateTime_IMPORT _PyDateTime_Import() +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; +} PyDateTime_CAPI; + +PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; +#define PyDateTime_IMPORT \ + do { \ + if(PyDateTimeAPI==NULL) \ + PyDateTimeAPI = _PyDateTime_Import(); \ + } while (0) typedef struct { PyObject_HEAD Modified: pypy/branch/fast-forward/pypy/module/cpyext/listobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/listobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/listobject.py Sun Jun 20 18:38:42 2010 @@ -72,9 +72,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyList_GET_SIZE(space, w_list): """Macro form of PyList_Size() without error checking. - - This macro returned an int. This might require changes in your - code for properly supporting 64-bit systems.""" + """ assert isinstance(w_list, W_ListObject) return len(w_list.wrappeditems) @@ -83,9 +81,7 @@ def PyList_Size(space, ref): """Return the length of the list object in list; this is equivalent to len(list) on a list object. - - This function returned an int. This might require changes in - your code for properly supporting 64-bit systems.""" + """ if not PyList_Check(space, ref): raise OperationError(space.w_TypeError, space.wrap("expected list object")) Modified: pypy/branch/fast-forward/pypy/module/cpyext/modsupport.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/modsupport.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/modsupport.py Sun Jun 20 18:38:42 2010 @@ -31,9 +31,12 @@ return w_mod +# This is actually the Py_InitModule4 function, +# renamed to refuse modules built against CPython headers. +# The implementation of Py_InitModule4 is in include/modsupport.inl @cpython_api([CONST_STRING, lltype.Ptr(PyMethodDef), CONST_STRING, PyObject, rffi.INT_real], PyObject) -def Py_InitModule4(space, name, methods, doc, w_self, apiver): +def _Py_InitPyPyModule(space, name, methods, doc, w_self, apiver): """ Create a new module object based on a name and table of functions, returning the new module object. If doc is non-NULL, it will be used to define the Modified: pypy/branch/fast-forward/pypy/module/cpyext/sequence.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/sequence.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/sequence.py Sun Jun 20 18:38:42 2010 @@ -10,9 +10,7 @@ def PySequence_Repeat(space, w_obj, count): """Return the result of repeating sequence object o count times, or NULL on failure. This is the equivalent of the Python expression o * count. - - This function used an int type for count. This might require - changes in your code for properly supporting 64-bit systems.""" + """ return space.mul(w_obj, space.wrap(count)) @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) Modified: pypy/branch/fast-forward/pypy/module/cpyext/state.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/state.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/state.py Sun Jun 20 18:38:42 2010 @@ -5,6 +5,8 @@ class State: + datetimeAPI = None # used in tests + def __init__(self, space): self.space = space self.reset() Modified: pypy/branch/fast-forward/pypy/module/cpyext/stringobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/stringobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/stringobject.py Sun Jun 20 18:38:42 2010 @@ -180,9 +180,7 @@ the address in *string may differ from its input value. If the reallocation fails, the original string object at *string is deallocated, *string is set to NULL, a memory exception is set, and -1 is returned. - - This function used an int type for newsize. This might - require changes in your code for properly supporting 64-bit systems.""" + """ # XXX always create a new string so far py_str = rffi.cast(PyStringObject, ref[0]) if not py_str.c_buffer: Modified: pypy/branch/fast-forward/pypy/module/cpyext/stubs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/stubs.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/stubs.py Sun Jun 20 18:38:42 2010 @@ -2967,13 +2967,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsUnicodeEscapeString(space, unicode): - """Encode a Unicode object using Unicode-Escape and return the result as Python - string object. Error handling is "strict". Return NULL if an exception was - raised by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject) def PyUnicode_DecodeRawUnicodeEscape(space, s, size, errors): """Create a Unicode object by decoding size bytes of the Raw-Unicode-Escape @@ -3043,13 +3036,6 @@ changes in your code for properly supporting 64-bit systems.""" raise NotImplementedError - at cpython_api([PyObject], PyObject) -def PyUnicode_AsASCIIString(space, unicode): - """Encode a Unicode object using ASCII and return the result as Python string - object. Error handling is "strict". Return NULL if an exception was raised - by the codec.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject) def PyUnicode_DecodeCharmap(space, s, size, mapping, errors): """Create a Unicode object by decoding size bytes of the encoded string s using Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py Sun Jun 20 18:38:42 2010 @@ -271,6 +271,8 @@ Py_DecRef(self.space, w_obj) state.non_heaptypes_w[:] = [] state.reset_borrowed_references() + from pypy.module.cpyext import cdatetime + cdatetime.datetimeAPI_dealloc(self.space) if self.check_and_print_leaks(): assert False, "Test leaks or loses object(s)." Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py Sun Jun 20 18:38:42 2010 @@ -79,3 +79,22 @@ w_date = api.PyDateTime_FromTimestamp(w_args) date = datetime.datetime.fromtimestamp(0) assert space.unwrap(space.str(w_date)) == str(date) + +class AppTestDatetime(AppTestCpythonExtensionBase): + def test_CAPI(self): + module = self.import_extension('foo', [ + ("get_types", "METH_NOARGS", + """ + PyDateTime_IMPORT; + return PyTuple_Pack(4, + PyDateTimeAPI->DateType, + PyDateTimeAPI->DateTimeType, + PyDateTimeAPI->TimeType, + PyDateTimeAPI->DeltaType); + """), + ]) + import datetime + assert module.get_types() == (datetime.date, + datetime.datetime, + datetime.time, + datetime.timedelta) Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_unicodeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_unicodeobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_unicodeobject.py Sun Jun 20 18:38:42 2010 @@ -49,7 +49,14 @@ space.newtuple([1, 2, 3]), None, None) self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString, space.wrap(''), None, None) + ascii = rffi.str2charp('ascii') + replace = rffi.str2charp('replace') + encoded = api.PyUnicode_AsEncodedString(space.wrap(u'sp?m'), + ascii, replace) + assert space.unwrap(encoded) == 'sp?m' rffi.free_charp(utf_8) + rffi.free_charp(replace) + rffi.free_charp(ascii) buf = rffi.unicode2wcharp(u"12345") api.PyUnicode_AsWideChar(space.wrap(u'longword'), buf, 5) @@ -143,3 +150,26 @@ rffi.free_wcharp(wbuf) assert space.type(w_str) is space.w_str assert space.str_w(w_str) == "abc?" + + def test_escape(self, space, api): + def test(ustr): + w_ustr = space.wrap(ustr.decode('Unicode-Escape')) + result = api.PyUnicode_AsUnicodeEscapeString(w_ustr) + assert space.eq_w(space.wrap(ustr), result) + + test('\\u674f\\u7f8e') + test('\\u0105\\u0107\\u017c\\u017a') + test('El Ni\\xf1o') + + def test_ascii(self, space, api): + ustr = "abcdef" + w_ustr = space.wrap(ustr.decode("ascii")) + result = api.PyUnicode_AsASCIIString(w_ustr) + + assert space.eq_w(space.wrap(ustr), result) + + w_ustr = space.wrap(u"abcd\xe9f") + result = api.PyUnicode_AsASCIIString(w_ustr) + assert result is None + + Modified: pypy/branch/fast-forward/pypy/module/cpyext/unicodeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/unicodeobject.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/unicodeobject.py Sun Jun 20 18:38:42 2010 @@ -105,10 +105,7 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PyUnicode_GET_SIZE(space, w_obj): """Return the size of the object. o has to be a PyUnicodeObject (not - checked). - - This function returned an int type. This might require changes - in your code for properly supporting 64-bit systems.""" + checked).""" assert isinstance(w_obj, unicodeobject.W_UnicodeObject) return space.int_w(space.len(w_obj)) @@ -190,7 +187,7 @@ return 0 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject) -def PyUnicode_AsEncodedString(space, w_unicode, encoding, errors): +def PyUnicode_AsEncodedString(space, w_unicode, llencoding, llerrors): """Encode a Unicode object and return the result as Python string object. encoding and errors have the same meaning as the parameters of the same name in the Unicode encode() method. The codec to be used is looked up using @@ -199,12 +196,22 @@ if not PyUnicode_Check(space, w_unicode): PyErr_BadArgument(space) - w_encoding = w_errors = None - if encoding: - w_encoding = rffi.charp2str(encoding) - if errors: - w_errors = rffi.charp2str(encoding) - return unicodetype.encode_object(space, w_unicode, w_encoding, w_errors) + encoding = errors = None + if llencoding: + encoding = rffi.charp2str(llencoding) + if llerrors: + errors = rffi.charp2str(llerrors) + return unicodetype.encode_object(space, w_unicode, encoding, errors) + + at cpython_api([PyObject], PyObject) +def PyUnicode_AsUnicodeEscapeString(space, w_unicode): + """Encode a Unicode object using Unicode-Escape and return the result as Python + string object. Error handling is "strict". Return NULL if an exception was + raised by the codec.""" + if not PyUnicode_Check(space, w_unicode): + PyErr_BadArgument(space) + + return unicodetype.encode_object(space, w_unicode, 'unicode-escape', 'strict') @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject) def PyUnicode_FromUnicode(space, wchar_p, length): @@ -300,6 +307,19 @@ w_errors = space.w_None return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors) + at cpython_api([PyObject], PyObject) +def PyUnicode_AsASCIIString(space, w_unicode): + """Encode a Unicode object using ASCII and return the result as Python string + object. Error handling is "strict". Return NULL if an exception was raised + by the codec.""" + try: + return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors? + except OperationError, e: + if e.match(space, space.w_UnicodeEncodeError): + return None + else: + raise + if sys.platform == 'win32': @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject) def PyUnicode_EncodeMBCS(space, wchar_p, length, errors): Modified: pypy/branch/fast-forward/pypy/module/imp/test/test_app.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/imp/test/test_app.py (original) +++ pypy/branch/fast-forward/pypy/module/imp/test/test_app.py Sun Jun 20 18:38:42 2010 @@ -71,7 +71,8 @@ import test_imp_extra_AUTO1 assert mod is test_imp_extra_AUTO1 - def test_load_module_pyc(self): + def test_load_module_pyc_1(self): + import os fn = self._pyc_file() try: descr = ('.pyc', 'rb', self.imp.PY_COMPILED) @@ -91,7 +92,7 @@ import test_imp_extra_AUTO3 assert mod is test_imp_extra_AUTO3 - def test_load_module_pyc(self): + def test_load_module_pyc_2(self): import os fn = self._pyc_file() try: Modified: pypy/branch/fast-forward/pypy/module/itertools/test/test_itertools.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/itertools/test/test_itertools.py (original) +++ pypy/branch/fast-forward/pypy/module/itertools/test/test_itertools.py Sun Jun 20 18:38:42 2010 @@ -130,7 +130,7 @@ raises(StopIteration, it.next) - def test_takewhile_wrongargs(self): + def test_dropwhile_wrongargs(self): import itertools it = itertools.dropwhile(None, [1]) Modified: pypy/branch/fast-forward/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/fast-forward/pypy/module/pypyjit/policy.py Sun Jun 20 18:38:42 2010 @@ -1,4 +1,4 @@ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy class PyPyJitPolicy(JitPolicy): Modified: pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py (original) +++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py Sun Jun 20 18:38:42 2010 @@ -222,7 +222,7 @@ while i < n+OFFSET: i = f(f(i)) return i - ''', 96, + ''', 98, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOAD_GLOBAL") @@ -263,7 +263,7 @@ x = a.f(i) i = a.f(x) return i - ''', 92, + ''', 93, ([20], 20), ([31], 32)) ops = self.get_by_bytecode("LOOKUP_METHOD") @@ -308,7 +308,7 @@ x = a.f(i) i = a.g(x) return i - ''', 105, + ''', 106, ([20], 20), ([31], 31)) ops = self.get_by_bytecode("LOOKUP_METHOD") Modified: pypy/branch/fast-forward/pypy/module/sys/app.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/app.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/app.py Sun Jun 20 18:38:42 2010 @@ -7,8 +7,35 @@ def excepthook(exctype, value, traceback): """Handle an exception by displaying it with a traceback on sys.stderr.""" - from traceback import print_exception - print_exception(exctype, value, traceback) + try: + from traceback import print_exception + print_exception(exctype, value, traceback) + except: + if not excepthook_failsafe(exctype, value): + raise + +def excepthook_failsafe(exctype, value): + # This version carefully tries to handle all bad cases (e.g. an + # ImportError looking for traceback.py), but may still raise. + # If it does, we get "Error calling sys.excepthook" from app_main.py. + try: + # first try to print the exception's class name + stderr = sys.stderr + stderr.write(getattr(exctype, '__name__', exctype)) + # then attempt to get the str() of the exception + try: + s = str(value) + except: + s = '' + # then print it, and don't worry too much about the extra space + # between the exception class and the ':' + if s: + stderr.write(': %s\n' % (s,)) + else: + stderr.write('\n') + return True # successfully printed at least the class and value + except: + return False # got an exception again... ignore, report the original def exit(exitcode=0): """Exit the interpreter by raising SystemExit(exitcode). Modified: pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py Sun Jun 20 18:38:42 2010 @@ -43,8 +43,6 @@ rlocale.setlocale(rlocale.LC_CTYPE, "") loc_codeset = rlocale.nl_langinfo(rlocale.CODESET) if loc_codeset: - if loc_codeset == 'ANSI_X3.4-1968': - loc_codeset = 'ascii' codecmod = space.getbuiltinmodule('_codecs') w_res = space.call_function(space.getattr(codecmod, space.wrap('lookup')), Modified: pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/test/test_sysmodule.py Sun Jun 20 18:38:42 2010 @@ -177,6 +177,26 @@ sys.stderr = savestderr assert err.getvalue().endswith("ValueError: 42\n") + def test_excepthook_failsafe_path(self): + import traceback + original_print_exception = traceback.print_exception + import cStringIO + savestderr = sys.stderr + err = cStringIO.StringIO() + sys.stderr = err + try: + traceback.print_exception = "foo" + eh = sys.__excepthook__ + try: + raise ValueError(42) + except ValueError, exc: + eh(*sys.exc_info()) + finally: + traceback.print_exception = original_print_exception + sys.stderr = savestderr + + assert err.getvalue() == "ValueError: 42\n" + # FIXME: testing the code for a lost or replaced excepthook in # Python/pythonrun.c::PyErr_PrintEx() is tricky. Modified: pypy/branch/fast-forward/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/branch/fast-forward/pypy/module/zipimport/interp_zipimport.py Sun Jun 20 18:38:42 2010 @@ -146,7 +146,7 @@ def import_py_file(self, space, modname, filename, buf, pkgpath): w = space.wrap w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) code_w = importing.parse_source_module(space, filename, buf) @@ -193,7 +193,7 @@ pkgpath) buf = buf[8:] # XXX ugly copy, should use sequential read instead w_mod = w(Module(space, w(modname))) - real_name = self.name + os.path.sep + self.corr_zname(filename) + real_name = self.filename + os.path.sep + self.corr_zname(filename) space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) result = importing.load_compiled_module(space, w(modname), w_mod, @@ -223,11 +223,6 @@ def load_module(self, space, fullname): w = space.wrap - w_modules = space.sys.get('modules') - try: - return space.getitem(w_modules, w(fullname)) - except OperationError, e: - pass filename = self.mangle(fullname) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: @@ -242,7 +237,7 @@ pass else: if is_package: - pkgpath = self.name + pkgpath = self.name + os.path.sep + filename else: pkgpath = None try: @@ -351,7 +346,6 @@ raise operationerrfmt(w_ZipImportError, "Cannot import %s from zipfile, recursion detected or" "already tried and failed", name) - return w_result except KeyError: zip_cache.cache[filename] = None try: @@ -363,6 +357,8 @@ prefix = name[len(filename):] if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP): prefix = prefix[1:] + if prefix and not prefix.endswith(ZIPSEP): + prefix += ZIPSEP w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file.NameToInfo, prefix)) zip_cache.set(filename, w_result) Modified: pypy/branch/fast-forward/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/zipimport/test/test_undocumented.py (original) +++ pypy/branch/fast-forward/pypy/module/zipimport/test/test_undocumented.py Sun Jun 20 18:38:42 2010 @@ -118,7 +118,7 @@ import zipimport, os zip_path = self.temp_zipfile(self.created_paths) try: - prefix = '_pkg' + prefix = '_pkg/' path = os.path.join(zip_path, prefix) zip_importer = zipimport.zipimporter(path) assert isinstance(zip_importer, zipimport.zipimporter) Modified: pypy/branch/fast-forward/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/branch/fast-forward/pypy/module/zipimport/test/test_zipimport.py Sun Jun 20 18:38:42 2010 @@ -114,10 +114,22 @@ from zipimport import _zip_directory_cache, zipimporter new_importer = zipimporter(self.zipfile) try: - assert zipimporter(self.zipfile) is new_importer + assert zipimporter(self.zipfile) is not new_importer finally: del _zip_directory_cache[self.zipfile] + def test_cache_subdir(self): + self.writefile(self, 'x.py', '') + self.writefile(self, 'sub/__init__.py', '') + self.writefile(self, 'sub/yy.py', '') + from zipimport import _zip_directory_cache, zipimporter + sub_importer = zipimporter(self.zipfile + '/sub') + main_importer = zipimporter(self.zipfile) + + assert main_importer is not sub_importer + assert main_importer.prefix == "" + assert sub_importer.prefix == "sub/" + def test_good_bad_arguments(self): from zipimport import zipimporter import os @@ -193,17 +205,50 @@ import zipimport z = zipimport.zipimporter(self.zipfile) sys.modules['uuu'] = lambda x : x + 1 - mod = z.load_module('uuu') - assert mod(3) == 4 + raises(ImportError, z.load_module, 'uuu') def test_package(self): import os, sys self.writefile(self, "xxuuu/__init__.py", "") self.writefile(self, "xxuuu/yy.py", "def f(x): return x") mod = __import__("xxuuu", globals(), locals(), ['yy']) - assert mod.__path__ + assert mod.__path__ == [self.zipfile + os.path.sep + "xxuuu"] + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuu" + os.path.sep + + "__init__.py") assert mod.yy.f(3) == 3 + def test_package_bug(self): + import os, sys + import new + mod = new.module('xxuuv') + mod.__path__ = [self.zipfile + '/xxuuv'] + sys.modules['xxuuv'] = mod + # + self.writefile(self, "xxuuv/__init__.py", "") + self.writefile(self, "xxuuv/yy.py", "def f(x): return x") + mod = __import__("xxuuv.yy", globals(), locals(), ['__doc__']) + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuv" + os.path.sep + + "yy.py") + assert mod.f(3) == 3 + + def test_pyc_in_package(self): + import os, sys + import new + mod = new.module('xxuuw') + mod.__path__ = [self.zipfile + '/xxuuw'] + sys.modules['xxuuw'] = mod + # + self.writefile(self, "xxuuw/__init__.py", "") + self.writefile(self, "xxuuw/zz.pyc", self.test_pyc) + mod = __import__("xxuuw.zz", globals(), locals(), ['__doc__']) + assert mod.__file__ == (self.zipfile + os.path.sep + + "xxuuw" + os.path.sep + + "zz.pyc") + assert mod.get_file() == mod.__file__ + assert mod.get_name() == mod.__name__ + def test_functions(self): import os import zipimport @@ -241,7 +286,7 @@ archive = importer.archive realprefix = importer.prefix allbutlast = self.zipfile.split(os.path.sep)[:-1] - prefix = 'directory' + prefix = 'directory/' assert archive == self.zipfile assert realprefix == prefix Modified: pypy/branch/fast-forward/pypy/objspace/flow/model.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/flow/model.py (original) +++ pypy/branch/fast-forward/pypy/objspace/flow/model.py Sun Jun 20 18:38:42 2010 @@ -416,13 +416,14 @@ lst.append(link) return result -def copygraph(graph, shallow=False, varmap={}): +def copygraph(graph, shallow=False, varmap={}, shallowvars=False): "Make a copy of a flow graph." blockmap = {} varmap = varmap.copy() + shallowvars = shallowvars or shallow def copyvar(v): - if shallow: + if shallowvars: return v try: return varmap[v] Modified: pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py Sun Jun 20 18:38:42 2010 @@ -467,7 +467,7 @@ # XXX fix this thing -import time, py +import time class DictInfo(object): _dict_infos = [] Modified: pypy/branch/fast-forward/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/dicttype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/dicttype.py Sun Jun 20 18:38:42 2010 @@ -4,7 +4,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.stdtypedef import StdTypeDef, SMM, no_hash_descr from pypy.objspace.std.register_all import register_all -from pypy.interpreter.error import OperationError dict_copy = SMM('copy', 1, doc='D.copy() -> a shallow copy of D') Modified: pypy/branch/fast-forward/pypy/objspace/std/frame.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/frame.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/frame.py Sun Jun 20 18:38:42 2010 @@ -130,7 +130,7 @@ w_result = getattr(f, attr)(w_1, w_2) break else: - raise pyopcde.BytecodeCorruption, "bad COMPARE_OP oparg" + raise pyopcode.BytecodeCorruption, "bad COMPARE_OP oparg" f.pushvalue(w_result) @@ -154,6 +154,7 @@ if space.config.objspace.std.optimized_comparison_op: StdObjSpaceFrame.COMPARE_OP = fast_COMPARE_OP if space.config.objspace.std.logspaceoptypes: + assert 0, "logspaceoptypes: a few fixes a missing here" StdObjSpace._space_op_types = [] for name, new in get_logging(): setattr(StdObjSpaceFrame, name, new) Modified: pypy/branch/fast-forward/pypy/objspace/std/settype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/settype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/settype.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr, SMM -from pypy.interpreter import gateway set_add = SMM('add', 2, doc='Add an element to a set.\n\nThis' Modified: pypy/branch/fast-forward/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/stringobject.py Sun Jun 20 18:38:42 2010 @@ -974,7 +974,6 @@ return formatter.format_string(w_string._value) def buffer__String(space, w_string): - from pypy.interpreter.buffer import StringBuffer return space.wrap(StringBuffer(w_string._value)) # register all methods Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_strutil.py Sun Jun 20 18:38:42 2010 @@ -2,8 +2,6 @@ from pypy.objspace.std.strutil import * from pypy.interpreter.error import OperationError -import py - class TestStrUtil: Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py Sun Jun 20 18:38:42 2010 @@ -289,7 +289,7 @@ assert (t * 1) is not t assert (t * 1) == t - def test_getslice(self): + def test_getslice_2(self): assert (5,2,3)[1:2] == (2,) def test_eq(self): Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py Sun Jun 20 18:38:42 2010 @@ -1001,12 +1001,12 @@ y.x = 3 assert y.x == 3 - def ga(self, name): - return 'GA' + def ga2(self, name): + return 'GA2' - X.__getattribute__ = ga + X.__getattribute__ = ga2 - assert y.x == 'GA' + assert y.x == 'GA2' class TestNewShortcut: Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_unicodeobject.py Sun Jun 20 18:38:42 2010 @@ -321,7 +321,7 @@ assert U(u'test') == u'test' assert U(u'test').__class__ is U - def test_call_unicode(self): + def test_call_unicode_2(self): class X(object): def __unicode__(self): return u'x' Modified: pypy/branch/fast-forward/pypy/objspace/std/transparent.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/transparent.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/transparent.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,6 @@ """ from pypy.interpreter import gateway -from pypy.interpreter.function import Function from pypy.interpreter.error import OperationError, operationerrfmt from pypy.objspace.std.proxyobject import * from pypy.objspace.std.typeobject import W_TypeObject Modified: pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/unicodetype.py Sun Jun 20 18:38:42 2010 @@ -172,6 +172,32 @@ # ____________________________________________________________ +def decode_error_handler(space): + def raise_unicode_exception_decode(errors, encoding, msg, s, + startingpos, endingpos): + raise OperationError(space.w_UnicodeDecodeError, + space.newtuple([space.wrap(encoding), + space.wrap(s), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_decode +decode_error_handler._annspecialcase_ = 'specialize:memo' + +def encode_error_handler(space): + def raise_unicode_exception_encode(errors, encoding, msg, u, + startingpos, endingpos): + raise OperationError(space.w_UnicodeEncodeError, + space.newtuple([space.wrap(encoding), + space.wrap(u), + space.wrap(startingpos), + space.wrap(endingpos), + space.wrap(msg)])) + return raise_unicode_exception_encode +encode_error_handler._annspecialcase_ = 'specialize:memo' + +# ____________________________________________________________ + def getdefaultencoding(space): return space.sys.defaultencoding @@ -193,21 +219,16 @@ w_encoder = space.sys.get_w_default_encoder() else: if errors is None or errors == 'strict': - try: - if encoding == 'ascii': - u = space.unicode_w(w_object) - return space.wrap(unicode_encode_ascii(u, len(u), None)) - if encoding == 'utf-8': - u = space.unicode_w(w_object) - return space.wrap(unicode_encode_utf_8(u, len(u), None)) - except UnicodeEncodeError, uee: - raise OperationError(space.w_UnicodeEncodeError, - space.newtuple([ - space.wrap(uee.encoding), - space.wrap(uee.object), - space.wrap(uee.start), - space.wrap(uee.end), - space.wrap(uee.reason)])) + if encoding == 'ascii': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_ascii(u, len(u), None, + errorhandler=eh)) + if encoding == 'utf-8': + u = space.unicode_w(w_object) + eh = encode_error_handler(space) + return space.wrap(unicode_encode_utf_8(u, len(u), None, + errorhandler=eh)) from pypy.module._codecs.interp_codecs import lookup_codec w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: @@ -226,19 +247,17 @@ if encoding is None: encoding = getdefaultencoding(space) if errors is None or errors == 'strict': - try: - if encoding == 'ascii': - # XXX error handling - s = space.bufferstr_w(w_obj) - return space.wrap(str_decode_ascii(s, len(s), None)[0]) - if encoding == 'utf-8': - s = space.bufferstr_w(w_obj) - return space.wrap(str_decode_utf_8(s, len(s), None)[0]) - except UnicodeDecodeError, ude: - raise OperationError(space.w_UnicodeDecodeError, space.newtuple( - [space.wrap(ude.encoding), space.wrap(ude.object), - space.wrap(ude.start), space.wrap(ude.end), - space.wrap(ude.reason)])) + if encoding == 'ascii': + # XXX error handling + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_ascii(s, len(s), None, + errorhandler=eh)[0]) + if encoding == 'utf-8': + s = space.bufferstr_w(w_obj) + eh = decode_error_handler(space) + return space.wrap(str_decode_utf_8(s, len(s), None, + errorhandler=eh)[0]) w_codecs = space.getbuiltinmodule("_codecs") w_decode = space.getattr(w_codecs, space.wrap("decode")) if errors is None: Modified: pypy/branch/fast-forward/pypy/rlib/jit.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/jit.py (original) +++ pypy/branch/fast-forward/pypy/rlib/jit.py Sun Jun 20 18:38:42 2010 @@ -6,26 +6,56 @@ from pypy.rlib.unroll import unrolling_iterable def purefunction(func): + """ Decorate a function as pure. Pure means precisely that: + + (1) the result of the call should not change if the arguments are + the same (same numbers or same pointers) + (2) it's fine to remove the call completely if we can guess the result + according to rule 1 + + Most importantly it doesn't mean that pure function has no observable + side effect, but those side effects can be ommited (ie caching). + For now, such a function should never raise an exception. + """ func._pure_function_ = True return func def hint(x, **kwds): + """ Hint for the JIT + + possible arguments are: + XXX + """ return x def dont_look_inside(func): + """ Make sure the JIT does not trace inside decorated function + (it becomes a call instead) + """ func._jit_look_inside_ = False return func def unroll_safe(func): + """ JIT can safely unroll loops in this function and this will + not lead to code explosion + """ func._jit_unroll_safe_ = True return func def loop_invariant(func): + """ Describes a function with no argument that returns an object that + is always the same in a loop. + + Use it only if you know what you're doing. + """ dont_look_inside(func) func._jit_loop_invariant_ = True return func def purefunction_promote(promote_args='all'): + """ A decorator that promotes all arguments and then calls the supplied + function + """ def decorator(func): import inspect purefunction(func) Modified: pypy/branch/fast-forward/pypy/rlib/parsing/test/test_regexparse.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/parsing/test/test_regexparse.py (original) +++ pypy/branch/fast-forward/pypy/rlib/parsing/test/test_regexparse.py Sun Jun 20 18:38:42 2010 @@ -24,7 +24,7 @@ assert r.recognize("kjsadfq3jlflASDF@#$") assert r.recognize("vka afj ASF# A") -def test_quoted(): +def test_quoted_1(): r = make_runner("\\(*") assert r.recognize("(") assert not r.recognize("\\(") @@ -77,7 +77,7 @@ assert not r.recognize("a") assert not r.recognize("c") -def test_quoted(): +def test_quoted_2(): r = make_runner('\\[|\\]|\\|') assert r.recognize("[") assert r.recognize("|") Modified: pypy/branch/fast-forward/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rgc.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rgc.py Sun Jun 20 18:38:42 2010 @@ -201,7 +201,6 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP - from pypy.rpython.lltypesystem import lltype hop.exception_is_here() return hop.genop('gc_heap_stats', [], resulttype=hop.r_result) Modified: pypy/branch/fast-forward/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/runicode.py (original) +++ pypy/branch/fast-forward/pypy/rlib/runicode.py Sun Jun 20 18:38:42 2010 @@ -17,7 +17,7 @@ # Note that Python3 uses a similar implementation. def UNICHR(c): assert not we_are_translated() - if c < sys.maxunicode or c > MAXUNICODE: + if c <= sys.maxunicode or c > MAXUNICODE: return unichr(c) else: c -= 0x10000 @@ -48,14 +48,12 @@ def raise_unicode_exception_decode(errors, encoding, msg, s, startingpos, endingpos): assert isinstance(s, str) - raise UnicodeDecodeError( - encoding, s[startingpos], startingpos, endingpos, msg) + raise UnicodeDecodeError(encoding, s, startingpos, endingpos, msg) def raise_unicode_exception_encode(errors, encoding, msg, u, startingpos, endingpos): assert isinstance(u, unicode) - raise UnicodeEncodeError( - encoding, u[startingpos], startingpos, endingpos, msg) + raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg) # ____________________________________________________________ # unicode decoding Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rbigint.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rbigint.py Sun Jun 20 18:38:42 2010 @@ -55,8 +55,6 @@ assert r1.tolong() == r2 def test_touint(self): - import sys - from pypy.rlib.rarithmetic import r_uint result = r_uint(sys.maxint + 42) rl = rbigint.fromint(sys.maxint).add(rbigint.fromint(42)) assert rl.touint() == result Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rlocale.py Sun Jun 20 18:38:42 2010 @@ -14,7 +14,8 @@ py.test.skip("polish locale unsupported") def teardown_class(cls): - setlocale(LC_ALL, cls.oldlocale) + if hasattr(cls, "oldlocale"): + setlocale(LC_ALL, cls.oldlocale) def test_setlocale_worked(self): assert u"??".isupper() Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rmmap.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rmmap.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rlib import rmmap as mmap from pypy.rlib.rmmap import RTypeError, RValueError, alloc, free -import sys class TestMMap: def setup_class(cls): Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_rpoll.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_rpoll.py Sun Jun 20 18:38:42 2010 @@ -1,4 +1,4 @@ -import thread +import thread, errno from pypy.rlib.rsocket import * from pypy.rlib.rpoll import * from pypy.rpython.test.test_llinterp import interpret @@ -34,8 +34,10 @@ assert events[0][1] & POLLOUT err = cli.connect_ex(servaddr) - # win32 oddity: returns WSAEISCONN when the connection finally succeed. - assert err == 0 or err == 10056 + # win32: returns WSAEISCONN when the connection finally succeed. + # Mac OS/X: returns EISCONN. + assert (err == 0 or err == 10056 or + err == getattr(errno, 'EISCONN', '???')) events = poll({servconn.fileno(): POLLIN, cli.fileno(): POLLIN}, timeout=100) Modified: pypy/branch/fast-forward/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/test/test_runicode.py (original) +++ pypy/branch/fast-forward/pypy/rlib/test/test_runicode.py Sun Jun 20 18:38:42 2010 @@ -2,6 +2,16 @@ import sys, random from pypy.rlib import runicode +def test_unichr(): + a = runicode.UNICHR(0xffff) + assert a == u'\uffff' + a = runicode.UNICHR(0x10000) + if sys.maxunicode < 0x10000: + assert len(a) == 2 # surrogates + else: + assert len(a) == 1 + + class UnicodeTests(object): def typeequals(self, x, y): assert x == y @@ -217,6 +227,10 @@ self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? class TestTranslation(object): + def setup_class(cls): + if len(runicode.UNICHR(0x10000)) == 2: + py.test.skip("these tests cannot run on the llinterp") + def test_utf8(self): from pypy.rpython.test.test_llinterp import interpret def f(x): Modified: pypy/branch/fast-forward/pypy/rpython/extfunc.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/extfunc.py (original) +++ pypy/branch/fast-forward/pypy/rpython/extfunc.py Sun Jun 20 18:38:42 2010 @@ -94,6 +94,7 @@ class BaseLazyRegistering(object): __metaclass__ = LazyRegisteringMeta + compilation_info = None def configure(self, CConfig): classes_seen = self.__dict__.setdefault('__classes_seen', {}) @@ -101,7 +102,11 @@ return from pypy.rpython.tool import rffi_platform as platform # copy some stuff - self.compilation_info = CConfig._compilation_info_ + if self.compilation_info is None: + self.compilation_info = CConfig._compilation_info_ + else: + self.compilation_info = self.compilation_info.merge( + CConfig._compilation_info_) self.__dict__.update(platform.configure(CConfig)) classes_seen[CConfig] = True Modified: pypy/branch/fast-forward/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/llinterp.py (original) +++ pypy/branch/fast-forward/pypy/rpython/llinterp.py Sun Jun 20 18:38:42 2010 @@ -111,16 +111,14 @@ self.traceback_frames = [] lines = [] for frame in frames: - logline = frame.graph.name + logline = frame.graph.name + "()" if frame.curr_block is None: logline += " " lines.append(logline) continue try: - logline += " " + self.typer.annotator.annotated[frame.curr_block].__module__ - except (KeyError, AttributeError): - # if the graph is from the GC it was not produced by the same - # translator :-( + logline += " " + self.typer.annotator.annotated[frame.curr_block].func.__module__ + except (KeyError, AttributeError, TypeError): logline += " " lines.append(logline) for i, operation in enumerate(frame.curr_block.operations): @@ -808,9 +806,9 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) - def op_cast_adr_to_int(self, adr): + def op_cast_adr_to_int(self, adr, mode): checkadr(adr) - return llmemory.cast_adr_to_int(adr) + return llmemory.cast_adr_to_int(adr, mode) def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py Sun Jun 20 18:38:42 2010 @@ -505,7 +505,7 @@ # additionally, this adds mess to __del__ "semantics" _all_callbacks = {} _all_callbacks_results = [] -_callback2obj = {} +_int2obj = {} _callback_exc_info = None def get_rtyper(): @@ -522,6 +522,13 @@ """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) + if isinstance(llobj, llmemory.AddressAsInt): + cobj = ctypes.cast(lltype2ctypes(llobj.adr), ctypes.c_void_p) + res = intmask(cobj.value) + _int2obj[res] = llobj.adr.ptr._obj + return res + if isinstance(llobj, llmemory.fakeaddress): + llobj = llobj.ptr or 0 T = lltype.typeOf(llobj) @@ -614,8 +621,9 @@ else: ctypes_func_type = get_ctypes_type(T) res = ctypes_func_type(callback) - _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container _all_callbacks[key] = res + key2 = intmask(ctypes.cast(res, ctypes.c_void_p).value) + _int2obj[key2] = container return res index = 0 @@ -724,9 +732,9 @@ container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): - cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value - if cobjkey in _callback2obj: - container = _callback2obj[cobjkey] + cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value) + if cobjkey in _int2obj: + container = _int2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), @@ -993,6 +1001,8 @@ """Cast a value to a result type, trying to use the same rules as C.""" if not isinstance(RESTYPE, lltype.LowLevelType): raise TypeError("rffi.cast() first arg should be a TYPE") + if isinstance(value, llmemory.AddressAsInt): + value = value.adr if isinstance(value, llmemory.fakeaddress): value = value.ptr or 0 TYPE1 = lltype.typeOf(value) Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py Sun Jun 20 18:38:42 2010 @@ -1,5 +1,5 @@ import array, weakref -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import llmemory # An "arena" is a large area of memory which can hold a number of # objects, not necessarily all of the same type or size. It's used by @@ -223,7 +223,8 @@ else: return self.arena._getid() < arena._getid() - def _cast_to_int(self): + def _cast_to_int(self, symbolic=False): + assert not symbolic return self.arena._getid() + self.offset Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py Sun Jun 20 18:38:42 2010 @@ -7,6 +7,7 @@ import weakref from pypy.rlib.objectmodel import Symbolic from pypy.rpython.lltypesystem import lltype +from pypy.tool.uid import uid class AddressOffset(Symbolic): @@ -478,11 +479,14 @@ else: return lltype.nullptr(EXPECTED_TYPE.TO) - def _cast_to_int(self): - # This is a bit annoying. We want this method to still work when the - # pointed-to object is dead + def _cast_to_int(self, symbolic=False): if self: - return self.ptr._cast_to_int(False) + if symbolic: + return AddressAsInt(self) + else: + # This is a bit annoying. We want this method to still work + # when the pointed-to object is dead + return self.ptr._cast_to_int(False) else: return 0 @@ -496,6 +500,29 @@ # ____________________________________________________________ +class AddressAsInt(Symbolic): + # a symbolic, rendered as an address cast to an integer. + def __init__(self, adr): + self.adr = adr + def annotation(self): + from pypy.annotation import model + return model.SomeInteger() + def lltype(self): + return lltype.Signed + def __eq__(self, other): + return self.adr == cast_int_to_adr(other) + def __ne__(self, other): + return self.adr != cast_int_to_adr(other) + def __nonzero__(self): + return bool(self.adr) + def __repr__(self): + try: + return '' % (self.adr.ptr,) + except AttributeError: + return '' % (uid(self),) + +# ____________________________________________________________ + class NullAddressError(Exception): pass @@ -603,12 +630,31 @@ def cast_adr_to_ptr(adr, EXPECTED_TYPE): return adr._cast_to_ptr(EXPECTED_TYPE) -def cast_adr_to_int(adr): - return adr._cast_to_int() +def cast_adr_to_int(adr, mode="emulated"): + # The following modes are supported before translation (after + # translation, it's all just a cast): + # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some + # number based on id(). The difference is that it works even if the + # address is that of a dead object. + # * mode="symbolic": returns an AddressAsInt instance, which can only be + # cast back to an address later. + # * mode="forced": uses rffi.cast() to return a real number. + assert mode in ("emulated", "symbolic", "forced") + res = adr._cast_to_int(symbolic = (mode != "emulated")) + if mode == "forced": + from pypy.rpython.lltypesystem.rffi import cast + res = cast(lltype.Signed, res) + return res _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + if isinstance(int, AddressAsInt): + return int.adr + try: + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + except ValueError: + from pypy.rpython.lltypesystem import ll2ctypes + ptr = ll2ctypes._int2obj[int]._as_ptr() return cast_ptr_to_adr(ptr) # ____________________________________________________________ Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py Sun Jun 20 18:38:42 2010 @@ -227,6 +227,8 @@ 'int_rshift': LLOp(canfold=True), 'int_xor': LLOp(canfold=True), + 'int_between': LLOp(canfold=True), # a <= b < c + 'int_add_ovf': LLOp(canraise=(OverflowError,), tryfold=True), 'int_add_nonneg_ovf': LLOp(canraise=(OverflowError,), tryfold=True), # ^^^ more efficient version when 2nd arg is nonneg @@ -263,7 +265,7 @@ 'uint_rshift': LLOp(canfold=True), 'uint_xor': LLOp(canfold=True), - 'float_is_true': LLOp(canfold=True), + 'float_is_true': LLOp(canfold=True), # it really means "x != 0.0" 'float_neg': LLOp(canfold=True), 'float_abs': LLOp(canfold=True), @@ -410,7 +412,7 @@ 'cast_ptr_to_adr': LLOp(sideeffects=False), 'cast_adr_to_ptr': LLOp(canfold=True), 'cast_adr_to_int': LLOp(sideeffects=False), - 'cast_int_to_adr': LLOp(canfold=True), # not implemented in llinterp + 'cast_int_to_adr': LLOp(canfold=True), 'get_group_member': LLOp(canfold=True), 'get_next_group_member':LLOp(canfold=True), Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py Sun Jun 20 18:38:42 2010 @@ -12,7 +12,6 @@ from pypy.lib.identity_dict import identity_dict from types import NoneType from sys import maxint -import struct import weakref TLS = tlsobject() @@ -301,9 +300,17 @@ class RttiStruct(Struct): _runtime_type_info = None + def _install_extras(self, rtti=False, **kwds): + if rtti: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, + name=self._name, + about=self)._obj + Struct._install_extras(self, **kwds) + def _attach_runtime_type_info_funcptr(self, funcptr, destrptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + raise TypeError("attachRuntimeTypeInfo: %r must have been built " + "with the rtti=True argument" % (self,)) if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -1877,7 +1884,8 @@ def cast_int_to_ptr(PTRTYPE, oddint): if oddint == 0: return nullptr(PTRTYPE.TO) - assert oddint & 1, "only odd integers can be cast back to ptr" + if not (oddint & 1): + raise ValueError("only odd integers can be cast back to ptr") return _ptr(PTRTYPE, oddint, solid=True) def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/opimpl.py Sun Jun 20 18:38:42 2010 @@ -197,6 +197,12 @@ assert isinstance(y, int) return intmask(x - y) +def op_int_between(a, b, c): + assert lltype.typeOf(a) is lltype.Signed + assert lltype.typeOf(b) is lltype.Signed + assert lltype.typeOf(c) is lltype.Signed + return a <= b < c + def op_int_and(x, y): if not isinstance(x, int): from pypy.rpython.lltypesystem import llgroup Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py Sun Jun 20 18:38:42 2010 @@ -13,8 +13,8 @@ Ptr, Struct, GcStruct, malloc, \ cast_pointer, cast_ptr_to_int, castable, nullptr, \ RuntimeTypeInfo, getRuntimeTypeInfo, typeOf, \ - Array, Char, Void, attachRuntimeTypeInfo, \ - FuncType, Bool, Signed, functionptr, FuncType, PyObject + Array, Char, Void, \ + FuncType, Bool, Signed, functionptr, PyObject from pypy.rpython.lltypesystem import lltype from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry @@ -22,6 +22,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel from pypy.lib.identity_dict import identity_dict +from pypy.rpython.lltypesystem.lloperation import llop # # There is one "vtable" per user class, with the following structure: @@ -60,7 +61,8 @@ CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), hints = {'immutable': True, 'shouldntbenull': True, - 'typeptr': True}) + 'typeptr': True}, + rtti = True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), @@ -72,7 +74,7 @@ hints = {'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) -NONGCOBJECTPTR = Ptr(OBJECT) +NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} @@ -348,18 +350,20 @@ if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) + kwds = {} + if self.gcflavor == 'gc': + kwds['rtti'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, - *llfields) + *llfields, + **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields - if self.gcflavor == 'gc': - attachRuntimeTypeInfo(self.object_type) def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) @@ -642,10 +646,12 @@ return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): - return cls.subclassrange_min <= subcls.subclassrange_min <= cls.subclassrange_max + return llop.int_between(Bool, cls.subclassrange_min, + subcls.subclassrange_min, + cls.subclassrange_max) def ll_issubclass_const(subcls, minid, maxid): - return minid <= subcls.subclassrange_min <= maxid + return llop.int_between(Bool, minid, subcls.subclassrange_min, maxid) def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rffi.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr -from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof, raw_memcopy +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic @@ -11,7 +11,6 @@ from pypy.rlib import rarithmetic, rgc from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.unroll import unrolling_iterable -from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.annlowlevel import llhelper @@ -785,7 +784,6 @@ # the hint is present in structures probed by rffi_platform. size = tp._hints.get('size') if size is None: - from pypy.rpython.lltypesystem import llmemory size = llmemory.sizeof(tp) # a symbolic result in this case return size if isinstance(tp, lltype.Ptr): @@ -814,7 +812,6 @@ if name == fieldname: return fieldoffsets[index] # a symbolic result as a fallback - from pypy.rpython.lltypesystem import llmemory return llmemory.offsetof(STRUCT, fieldname) offsetof._annspecialcase_ = 'specialize:memo' Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rlist.py Sun Jun 20 18:38:42 2010 @@ -388,6 +388,7 @@ ('index', Signed))) self.ll_listiter = ll_listiter self.ll_listnext = ll_listnext + self.ll_getnextindex = ll_getnextindex def ll_listiter(ITERPTR, lst): iter = malloc(ITERPTR.TO) @@ -402,3 +403,6 @@ raise StopIteration iter.index = index + 1 # cannot overflow because index < l.length return l.ll_getitem_fast(index) + +def ll_getnextindex(iter): + return iter.index Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rstr.py Sun Jun 20 18:38:42 2010 @@ -18,7 +18,6 @@ from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory from pypy.tool.sourcetools import func_with_new_name -from pypy.rpython.annlowlevel import hlstr # ____________________________________________________________ # @@ -297,7 +296,7 @@ s = mallocunicode(lgt) for i in range(lgt): if ord(str.chars[i]) > 127: - raise UnicodeDecodeError("ascii", hlstr(str), 0, lgt, "ascii codec can't encode %d" % ord(str.chars[i])) + raise UnicodeDecodeError s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s ll_str2unicode.oopspec = 'str.str2unicode(str)' Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sun Jun 20 18:38:42 2010 @@ -15,7 +15,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper -from pypy.tool.udir import udir class TestLL2Ctypes(object): @@ -1242,6 +1241,15 @@ res = interpret(f, []) assert res == 6 + def test_force_to_int(self): + S = lltype.Struct('S') + p = lltype.malloc(S, flavor='raw') + a = llmemory.cast_ptr_to_adr(p) + i = llmemory.cast_adr_to_int(a, "forced") + assert type(i) is int + assert i == llmemory.cast_adr_to_int(a, "forced") + lltype.free(p, flavor='raw') + class TestPlatform(object): def test_lib_on_libpaths(self): from pypy.translator.platform import platform Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_llmemory.py Sun Jun 20 18:38:42 2010 @@ -624,3 +624,24 @@ # the following line crashes if the array is dead ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) ptr1[0] = NULL + +def test_cast_adr_to_int(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + i = cast_adr_to_int(adr, mode="symbolic") + assert isinstance(i, AddressAsInt) + assert cast_int_to_adr(i) == adr + assert cast_adr_to_int(NULL, mode="symbolic") == 0 + assert cast_int_to_adr(0) == NULL + # + i = cast_adr_to_int(adr, mode="emulated") + assert type(i) is int + i = cast_adr_to_int(NULL, mode="emulated") + assert type(i) is int and i == 0 + # + i = cast_adr_to_int(adr, mode="forced") + assert type(i) is int + #assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details + i = cast_adr_to_int(NULL, mode="forced") + assert type(i) is int and i == 0 Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py Sun Jun 20 18:38:42 2010 @@ -363,22 +363,25 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) py.test.raises(ValueError, "getRuntimeTypeInfo(S)") - pinf0 = attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) + pinfx = getRuntimeTypeInfo(S) + pinf0 = attachRuntimeTypeInfo(S) # no-op, really assert pinf0._obj.about == S + assert pinf0 == pinfx pinf = getRuntimeTypeInfo(S) assert pinf == pinf0 pinf1 = getRuntimeTypeInfo(S) assert pinf == pinf1 - Z = GcStruct('z', ('x', Unsigned)) - attachRuntimeTypeInfo(Z) + Z = GcStruct('z', ('x', Unsigned), rtti=True) assert getRuntimeTypeInfo(Z) != pinf0 - Sbis = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(Sbis) + Sbis = GcStruct('s', ('x', Signed), rtti=True) assert getRuntimeTypeInfo(Sbis) != pinf0 assert Sbis != S # the attached runtime type info distinguishes them + Ster = GcStruct('s', ('x', Signed), rtti=True) + assert Sbis != Ster # the attached runtime type info distinguishes them def test_getRuntimeTypeInfo_destrpointer(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -399,12 +402,12 @@ assert pinf._obj.query_funcptr == qp def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) + S = GcStruct('s', ('x', Signed), rtti=True) attachRuntimeTypeInfo(S) s = malloc(S) s.x = 0 assert runtime_type_info(s) == getRuntimeTypeInfo(S) - S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + S1 = GcStruct('s1', ('sub', S), ('x', Signed), rtti=True) attachRuntimeTypeInfo(S1) s1 = malloc(S1) s1.sub.x = 0 @@ -719,7 +722,6 @@ def test_name_clash(): import re - from pypy.rpython.lltypesystem import lltype fn = lltype.__file__ if fn.lower().endswith('pyc') or fn.lower().endswith('pyo'): fn = fn[:-1] Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py Sun Jun 20 18:38:42 2010 @@ -720,7 +720,7 @@ return pos elif sys.platform == 'darwin': - from pypy.rpython.lltypesystem import lltype, rffi + from pypy.rpython.lltypesystem import rffi sysctlbyname = rffi.llexternal('sysctlbyname', [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP, Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gc/marksweep.py Sun Jun 20 18:38:42 2010 @@ -242,7 +242,6 @@ # 3. walk the list of objects-with-del and for the ones not marked: # call __del__, move the object to the list of object-without-del import time - from pypy.rpython.lltypesystem.lloperation import llop debug_start("gc-collect") start_time = time.time() self.collect_in_progress = True Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py Sun Jun 20 18:38:42 2010 @@ -114,12 +114,14 @@ fnptr._obj._name + '_reload', graph=graph2) c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2)], FUNC1.RESULT) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], resulttype=lltype.Ptr(HELPERFUNC)) hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, Constant(None, lltype.Void)], + [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, + Constant(None, lltype.Void)], resultvar=hop.spaceop.result) self.pop_roots(hop, livevars) @@ -151,7 +153,8 @@ def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata gcdata._gc_collect_stack_root = collect_stack_root - pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback)) + pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback), + gcrootanchor) def walk_stack_from(self): curframe = lltype.malloc(WALKFRAME, flavor='raw') @@ -160,7 +163,7 @@ # Walk over all the pieces of stack. They are in a circular linked # list of structures of 7 words, the 2 first words being prev/next. # The anchor of this linked list is: - anchor = llop.gc_asmgcroot_static(llmemory.Address, 3) + anchor = llmemory.cast_ptr_to_adr(gcrootanchor) initialframedata = anchor.address[1] stackscount = 0 while initialframedata != anchor: # while we have not looped back @@ -475,8 +478,22 @@ llmemory.Address), ) +# We have a circular doubly-linked list of all the ASM_FRAMEDATAs currently +# alive. The list's starting point is given by 'gcrootanchor', which is not +# a full ASM_FRAMEDATA but only contains the prev/next pointers: +ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference()) +ASM_FRAMEDATA_HEAD_PTR.TO.become(lltype.Struct('ASM_FRAMEDATA_HEAD', + ('prev', ASM_FRAMEDATA_HEAD_PTR), + ('next', ASM_FRAMEDATA_HEAD_PTR) + )) +gcrootanchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, immortal=True) +gcrootanchor.prev = gcrootanchor +gcrootanchor.next = gcrootanchor +c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', - [ASM_CALLBACK_PTR], + [ASM_CALLBACK_PTR, + ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True) Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_boehm.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_boehm.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_boehm.py Sun Jun 20 18:38:42 2010 @@ -40,7 +40,7 @@ assert f is not None def test_boehm_finalizer___del__(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -58,7 +58,8 @@ assert f is not None def test_boehm_finalizer_nomix___del___and_pyobj(): - S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) + S = lltype.GcStruct("S", ('x', lltype.Signed), + ('y', lltype.Ptr(lltype.PyObject)), rtti=True) def f(s): s.x = 1 def type_info_S(p): Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/test/test_refcounting.py Sun Jun 20 18:38:42 2010 @@ -175,7 +175,7 @@ assert len(ops['gc_free']) == 1 def test_deallocator_with_destructor(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) def f(s): s.x = 1 def type_info_S(p): @@ -192,9 +192,9 @@ graph, t = make_deallocator(S) def test_caching_dynamic_deallocator(): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) - T = lltype.GcStruct("T", ('x', lltype.Signed)) + S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) + S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) + T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): Modified: pypy/branch/fast-forward/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/test/test_lldict.py Sun Jun 20 18:38:42 2010 @@ -100,7 +100,7 @@ _TYPE = llmemory.Address def __init__(self, intval): self.intval = intval - def _cast_to_int(self): + def _cast_to_int(self, symbolic="?"): return self.intval def __repr__(self): return '' % (self.intval & (sys.maxint*2+1),) Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/module/ll_time.py (original) +++ pypy/branch/fast-forward/pypy/rpython/module/ll_time.py Sun Jun 20 18:38:42 2010 @@ -17,24 +17,28 @@ STRUCT_TIMEB = 'struct __timeb64' includes = ['winsock2.h', 'windows.h', TIME_H, 'sys/types.h', 'sys/timeb.h'] + need_rusage = False else: TIME_H = 'sys/time.h' FTIME = 'ftime' STRUCT_TIMEB = 'struct timeb' includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', - 'sys/types.h', 'unistd.h', 'sys/timeb.h'] + 'sys/types.h', 'unistd.h', 'sys/timeb.h', + 'sys/time.h', 'sys/resource.h'] + need_rusage = True class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=includes ) - CLOCK_T = platform.SimpleType('clock_t', rffi.INT) TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), ('tv_usec', rffi.INT)]) HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') HAVE_FTIME = platform.Has(FTIME) - + if need_rusage: + RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL), + ('ru_stime', TIMEVAL)]) if sys.platform == 'freebsd7': libraries = ['compat'] @@ -49,21 +53,20 @@ TIMEB = platform.Struct(STRUCT_TIMEB, [('time', rffi.INT), ('millitm', rffi.INT)]) -constant_names = ['CLOCKS_PER_SEC', 'CLK_TCK', 'EINTR'] +constant_names = ['RUSAGE_SELF', 'EINTR'] for const in constant_names: setattr(CConfig, const, platform.DefinedConstantInteger(const)) defs_names = ['GETTIMEOFDAY_NO_TZ'] for const in defs_names: setattr(CConfig, const, platform.Defined(const)) +def decode_timeval(t): + return (float(rffi.cast(lltype.Signed, t.c_tv_sec)) + + float(rffi.cast(lltype.Signed, t.c_tv_usec)) * 0.000001) + class RegisterTime(BaseLazyRegistering): def __init__(self): self.configure(CConfig) - if self.CLOCKS_PER_SEC is None: - if self.CLK_TCK is None: - self.CLOCKS_PER_SEC = 1000000 - else: - self.CLOCKS_PER_SEC = self.CLK_TCK self.TIMEVALP = lltype.Ptr(self.TIMEVAL) @registering(time.time) @@ -109,10 +112,7 @@ errcode = c_gettimeofday(t, void) if rffi.cast(rffi.LONG, errcode) == 0: - result = float(rffi.cast(lltype.Signed, t.c_tv_sec)) \ - + float(rffi.cast(lltype.Signed, t.c_tv_usec)) \ - * 0.000001 - + result = decode_timeval(t) lltype.free(t, flavor='raw') if result != -1: return result @@ -129,8 +129,6 @@ @registering(time.clock) def register_time_clock(self): - c_clock = self.llexternal('clock', [], self.CLOCK_T, - threadsafe=False) if sys.platform == 'win32': # hacking to avoid LARGE_INTEGER which is a union... A = lltype.FixedSizeArray(lltype.SignedLongLong, 1) @@ -157,9 +155,19 @@ lltype.free(a, flavor='raw') return float(diff) / state.divisor else: + RUSAGE = self.RUSAGE + RUSAGE_SELF = self.RUSAGE_SELF or 0 + c_getrusage = self.llexternal('getrusage', + [rffi.INT, lltype.Ptr(RUSAGE)], + lltype.Void, + threadsafe=False) def time_clock_llimpl(): - result = c_clock() - return float(result) / self.CLOCKS_PER_SEC + a = lltype.malloc(RUSAGE, flavor='raw') + c_getrusage(RUSAGE_SELF, a) + result = (decode_timeval(a.c_ru_utime) + + decode_timeval(a.c_ru_stime)) + lltype.free(a, flavor='raw') + return result return extdef([], float, llimpl=time_clock_llimpl, export_name='ll_time.ll_time_clock') Modified: pypy/branch/fast-forward/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/normalizecalls.py (original) +++ pypy/branch/fast-forward/pypy/rpython/normalizecalls.py Sun Jun 20 18:38:42 2010 @@ -292,6 +292,13 @@ else: return cmp(self.orderwitness, other.orderwitness) + # support for implementing int_between: (a<=b 5: + key = llmemory.cast_ptr_to_adr(a) + else: + key = llmemory.cast_ptr_to_adr(b) + return d[key] + + assert self.interpret(func, [3]) == 456 + def test_prebuilt_list_of_addresses(self): from pypy.rpython.lltypesystem import llmemory Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rfloat.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rfloat.py Sun Jun 20 18:38:42 2010 @@ -77,7 +77,6 @@ assert res == fn(2.34) def test_longlong_conversion(self): - import sys def fn(f): return r_longlong(f) Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rint.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rint.py Sun Jun 20 18:38:42 2010 @@ -169,7 +169,6 @@ assert res == 0 def test_truediv(self): - import operator def f(n, m): return operator.truediv(n, m) res = self.interpret(f, [20, 4]) Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py Sun Jun 20 18:38:42 2010 @@ -10,7 +10,6 @@ from pypy.rpython.lltypesystem import rlist as ll_rlist from pypy.rpython.ootypesystem import rlist as oo_rlist from pypy.rpython.rint import signed_repr -from pypy.translator.translator import TranslationContext from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin @@ -1070,7 +1069,7 @@ assert res == 0 - def test_getitem_exc(self): + def test_getitem_exc_1(self): def f(x): l = [1] return l[x] @@ -1115,7 +1114,7 @@ res = self.interpret(f, [0]) assert res == 1 - def test_getitem_exc(self): + def test_getitem_exc_2(self): def f(x): l = [1] return l[x] Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rptr.py Sun Jun 20 18:38:42 2010 @@ -36,8 +36,7 @@ assert s.ll_ptrtype == PS2 def test_runtime_type_info(): - S = GcStruct('s', ('x', Signed)) - attachRuntimeTypeInfo(S) + S = GcStruct('s', ('x', Signed), rtti=True) def ll_example(p): return (runtime_type_info(p), runtime_type_info(p) == getRuntimeTypeInfo(S)) @@ -176,6 +175,31 @@ res = interpret(fn, [5]) assert res is True +def test_cast_adr_to_int(): + S = Struct('S') + p = malloc(S, immortal=True) + def fn(n): + a = llmemory.cast_ptr_to_adr(p) + if n == 2: + return llmemory.cast_adr_to_int(a, "emulated") + elif n == 4: + return llmemory.cast_adr_to_int(a, "symbolic") + else: + return llmemory.cast_adr_to_int(a, "forced") + + res = interpret(fn, [2]) + assert type(res) is int + assert res == cast_ptr_to_int(p) + # + res = interpret(fn, [4]) + assert isinstance(res, llmemory.AddressAsInt) + assert llmemory.cast_int_to_adr(res) == llmemory.cast_ptr_to_adr(p) + # + res = interpret(fn, [6]) + assert type(res) is int + from pypy.rpython.lltypesystem import rffi + assert res == rffi.cast(Signed, p) + def test_flavored_malloc(): T = GcStruct('T', ('y', Signed)) def fn(n): Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rrange.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rrange.py Sun Jun 20 18:38:42 2010 @@ -160,6 +160,15 @@ res = self.interpret(fn, []) assert res == 0 + def test_enumerate(self): + def fn(n): + for i, x in enumerate([123, 456, 789, 654]): + if i == n: + return x + return 5 + res = self.interpret(fn, [2]) + assert res == 789 + class TestLLtype(BaseTestRrange, LLRtypeMixin): from pypy.rpython.lltypesystem import rrange Modified: pypy/branch/fast-forward/pypy/rpython/test/test_rvirtualizable2.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/test/test_rvirtualizable2.py (original) +++ pypy/branch/fast-forward/pypy/rpython/test/test_rvirtualizable2.py Sun Jun 20 18:38:42 2010 @@ -311,7 +311,7 @@ assert res == 2323 def test_access_directly_stop_at_dont_look_inside(self): - from pypy.rlib.jit import hint, dont_look_inside + from pypy.rlib.jit import dont_look_inside class A: _virtualizable2_ = ['x'] Modified: pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py Sun Jun 20 18:38:42 2010 @@ -752,7 +752,7 @@ 'struct sockaddr_in' sin_port INT """ - import sys, getopt + import getopt opts, args = getopt.gnu_getopt(sys.argv[1:], 'h:') if not args: print >> sys.stderr, doc Modified: pypy/branch/fast-forward/pypy/tool/gcc_cache.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/gcc_cache.py (original) +++ pypy/branch/fast-forward/pypy/tool/gcc_cache.py Sun Jun 20 18:38:42 2010 @@ -1,6 +1,5 @@ - from pypy.tool.autopath import pypydir -from pypy.translator.platform import platform, CompilationError +from pypy.translator.platform import CompilationError from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.compat import md5 import py @@ -8,6 +7,9 @@ cache_dir_root = py.path.local(pypydir).join('_cache').ensure(dir=1) def cache_file_path(c_files, eci, cachename): + "Builds a filename to cache compilation data" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform cache_dir = cache_dir_root.join(cachename).ensure(dir=1) filecontents = [c_file.read() for c_file in c_files] key = repr((filecontents, eci, platform.key())) @@ -15,6 +17,9 @@ return cache_dir.join(hash) def build_executable_cache(c_files, eci): + "Builds and run a program; caches the result" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'build_executable_cache') try: return path.read() @@ -24,6 +29,9 @@ return result.out def try_compile_cache(c_files, eci): + "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + # Import 'platform' every time, the compiler may have been changed + from pypy.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() @@ -33,9 +41,9 @@ try: platform.compile(c_files, eci) data = 'True' + path.write(data) except CompilationError, e: data = 'FAIL\n%s\n' % (e,) - path.write(data) if data.startswith('True'): return True else: Modified: pypy/branch/fast-forward/pypy/tool/runsubprocess.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/runsubprocess.py (original) +++ pypy/branch/fast-forward/pypy/tool/runsubprocess.py Sun Jun 20 18:38:42 2010 @@ -5,7 +5,6 @@ import sys import os -import warnings from subprocess import PIPE, Popen def run_subprocess(executable, args, env=None, cwd=None): @@ -28,7 +27,9 @@ if __name__ == '__main__': + import gc while True: + gc.collect() operation = sys.stdin.readline() if not operation: sys.exit() @@ -46,16 +47,26 @@ # do this at import-time, when the process is still tiny _source = os.path.dirname(os.path.abspath(__file__)) _source = os.path.join(_source, 'runsubprocess.py') # and not e.g. '.pyc' - # Let's not hear about os.popen2's deprecation. - warnings.filterwarnings("ignore", ".*popen2.*", DeprecationWarning, - "pypy.tool.runsubprocess") - _child_stdin, _child_stdout = os.popen2( - "'%s' '%s'" % (sys.executable, _source)) + + def spawn_subprocess(): + global _child + _child = Popen([sys.executable, _source], bufsize=0, + stdin=PIPE, stdout=PIPE, close_fds=True) + spawn_subprocess() + + def cleanup_subprocess(): + global _child + _child = None + import atexit; atexit.register(cleanup_subprocess) def _run(*args): - _child_stdin.write('%r\n' % (args,)) - _child_stdin.flush() - results = _child_stdout.readline() + try: + _child.stdin.write('%r\n' % (args,)) + except (OSError, IOError): + # lost the child. Try again... + spawn_subprocess() + _child.stdin.write('%r\n' % (args,)) + results = _child.stdout.readline() assert results.startswith('(') results = eval(results) if results[0] is None: Modified: pypy/branch/fast-forward/pypy/tool/sourcetools.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/sourcetools.py (original) +++ pypy/branch/fast-forward/pypy/tool/sourcetools.py Sun Jun 20 18:38:42 2010 @@ -129,7 +129,6 @@ for name in names: if name not in kwargs: kwargs[name] = getattr(fromcode, name) - import new return new.code( kwargs['co_argcount'], kwargs['co_nlocals'], Modified: pypy/branch/fast-forward/pypy/tool/test/test_runsubprocess.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/test/test_runsubprocess.py (original) +++ pypy/branch/fast-forward/pypy/tool/test/test_runsubprocess.py Sun Jun 20 18:38:42 2010 @@ -30,3 +30,12 @@ assert returncode == 1 assert stdout == '' assert 'no/such/filename' in stderr + +def test_recover_lost_process(): + if not hasattr(os, 'fork'): + py.test.skip("there is no os.fork()") + from pypy.tool import runsubprocess + import signal + os.kill(runsubprocess._child.pid, signal.SIGTERM) + runsubprocess._child.wait() + test_echo() Modified: pypy/branch/fast-forward/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/funcgen.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/funcgen.py Sun Jun 20 18:38:42 2010 @@ -318,6 +318,7 @@ def gen_op(self, op): macro = 'OP_%s' % op.opname.upper() + line = None if op.opname.startswith('gc_'): meth = getattr(self.gcpolicy, macro, None) if meth: @@ -326,7 +327,7 @@ meth = getattr(self, macro, None) if meth: line = meth(op) - if meth is None: + if line is None: lst = [self.expr(v) for v in op.args] lst.append(self.expr(op.result)) line = '%s(%s);' % (macro, ', '.join(lst)) @@ -849,5 +850,16 @@ return 'PYPY_DEBUG_CATCH_EXCEPTION("%s", %s, %s);' % ( self.getdebugfunctionname(), gottype, ' || '.join(exprs)) + def OP_INT_BETWEEN(self, op): + if (isinstance(op.args[0], Constant) and + isinstance(op.args[2], Constant) and + op.args[2].value - op.args[0].value == 1): + # (a <= b < a+1) ----> (b == a) + return '%s = (%s == %s); /* was INT_BETWEEN */' % ( + self.expr(op.result), + self.expr(op.args[1]), + self.expr(op.args[0])) + else: + return None # use the default assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/branch/fast-forward/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/gcc/test/test_asmgcroot.py Sun Jun 20 18:38:42 2010 @@ -65,8 +65,13 @@ env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),) else: env = '' - g = os.popen( - '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + cwd = os.getcwd() + try: + os.chdir(str(exe_name.dirpath())) + g = os.popen( + '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r') + finally: + os.chdir(cwd) for line in g: print >> sys.stderr, 'RUN:', line.rstrip() lines.append(line) Modified: pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py Sun Jun 20 18:38:42 2010 @@ -1283,20 +1283,13 @@ if self.format == 'msvc': print >> output, """\ - /* A circular doubly-linked list of all - * the ASM_FRAMEDATAs currently alive - */ - struct asm_framedata { - struct asm_framedata* prev; - struct asm_framedata* next; - } __gcrootanchor = { &__gcrootanchor, &__gcrootanchor }; - /* See description in asmgcroot.py */ __declspec(naked) long pypy_asm_stackwalk(void *callback) { __asm { - mov\tedx, DWORD PTR [esp+4]\t; my argument, which is the callback + mov\tedx, DWORD PTR [esp+4]\t; 1st argument, which is the callback + mov\tecx, DWORD PTR [esp+8]\t; 2nd argument, which is gcrootanchor mov\teax, esp\t\t; my frame top address push\teax\t\t\t; ASM_FRAMEDATA[6] push\tebp\t\t\t; ASM_FRAMEDATA[5] @@ -1307,10 +1300,10 @@ ; Add this ASM_FRAMEDATA to the front of the circular linked ; list. Let's call it 'self'. - mov\teax, DWORD PTR [__gcrootanchor+4]\t\t; next = gcrootanchor->next + mov\teax, DWORD PTR [ecx+4]\t\t; next = gcrootanchor->next push\teax\t\t\t\t\t\t\t\t\t; self->next = next - push\tOFFSET __gcrootanchor ; self->prev = gcrootanchor - mov\tDWORD PTR [__gcrootanchor+4], esp\t\t; gcrootanchor->next = self + push\tecx ; self->prev = gcrootanchor + mov\tDWORD PTR [ecx+4], esp\t\t; gcrootanchor->next = self mov\tDWORD PTR [eax+0], esp\t\t\t\t\t; next->prev = self call\tedx\t\t\t\t\t\t; invoke the callback @@ -1343,7 +1336,8 @@ print >> output, """\ /* See description in asmgcroot.py */ - movl\t4(%esp), %edx\t/* my argument, which is the callback */ + movl\t4(%esp), %edx\t/* 1st argument, which is the callback */ + movl\t8(%esp), %ecx\t/* 2nd argument, which is gcrootanchor */ movl\t%esp, %eax\t/* my frame top address */ pushl\t%eax\t\t/* ASM_FRAMEDATA[6] */ pushl\t%ebp\t\t/* ASM_FRAMEDATA[5] */ @@ -1354,10 +1348,10 @@ /* Add this ASM_FRAMEDATA to the front of the circular linked */ /* list. Let's call it 'self'. */ - movl\t__gcrootanchor + 4, %eax\t/* next = gcrootanchor->next */ + movl\t4(%ecx), %eax\t/* next = gcrootanchor->next */ pushl\t%eax\t\t\t\t/* self->next = next */ - pushl\t$__gcrootanchor\t\t\t/* self->prev = gcrootanchor */ - movl\t%esp, __gcrootanchor + 4\t/* gcrootanchor->next = self */ + pushl\t%ecx\t\t\t/* self->prev = gcrootanchor */ + movl\t%esp, 4(%ecx)\t/* gcrootanchor->next = self */ movl\t%esp, 0(%eax)\t\t\t/* next->prev = self */ /* note: the Mac OS X 16 bytes aligment must be respected. */ @@ -1378,7 +1372,7 @@ /* the return value is the one of the 'call' above, */ /* because %eax (and possibly %edx) are unmodified */ ret - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) + """ _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk', darwin='', @@ -1388,17 +1382,6 @@ for label, state, is_range in self.gcmaptable: label = label[1:] print >> output, "extern void* %s;" % label - else: - print >> output, """\ - /* A circular doubly-linked list of all */ - /* the ASM_FRAMEDATAs currently alive */ - .data - .align 4 - .globl __gcrootanchor - __gcrootanchor: - .long\t__gcrootanchor /* prev */ - .long\t__gcrootanchor /* next */ - """.replace("__gcrootanchor", _globalname("__gcrootanchor")) shapes = {} shapelines = [] @@ -1437,6 +1420,8 @@ """ else: print >> output, """\ + .data + .align 4 .globl __gcmapstart __gcmapstart: """.replace("__gcmapstart", _globalname("__gcmapstart")) Modified: pypy/branch/fast-forward/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/genc.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/genc.py Sun Jun 20 18:38:42 2010 @@ -33,7 +33,7 @@ def first(self): platform = self.compiler.platform - if platform.name == 'darwin': + if platform.name.startswith('darwin'): # XXX incredible hack for darwin cfiles = self.compiler.cfiles STR = '/*--no-profiling-for-this-file!--*/' @@ -227,7 +227,7 @@ funcgen.patch_graph(copy_graph=False) return db - def generate_source(self, db=None, defines={}): + def generate_source(self, db=None, defines={}, exe_name=None): assert self.c_source_filename is None translator = self.translator @@ -271,7 +271,7 @@ defines = defines) self.c_source_filename = py.path.local(cfile) self.extrafiles = self.eventually_copy(extra) - self.gen_makefile(targetdir) + self.gen_makefile(targetdir, exe_name=exe_name) return cfile def eventually_copy(self, cfiles): @@ -482,7 +482,7 @@ # build main program eci = self.get_eci() kw = {} - if self.translator.platform.so_ext == 'so': + if self.translator.platform.cc == 'gcc': kw['libraries'] = [self.shared_library_name.purebasename[3:]] kw['library_dirs'] = [self.targetdir] else: @@ -516,6 +516,10 @@ extra_opts += ['-j', str(self.config.translation.make_jobs)] self.translator.platform.execute_makefile(self.targetdir, extra_opts) + if shared: + self.shared_library_name = self.executable_name.new( + purebasename='lib' + self.executable_name.purebasename, + ext=self.translator.platform.so_ext) else: compiler = CCompilerDriver(self.translator.platform, [self.c_source_filename] + self.extrafiles, @@ -531,6 +535,8 @@ def gen_makefile(self, targetdir, exe_name=None): cfiles = [self.c_source_filename] + self.extrafiles + if exe_name is not None: + exe_name = targetdir.join(exe_name) mk = self.translator.platform.gen_makefile( cfiles, self.eci, path=targetdir, exe_name=exe_name, Modified: pypy/branch/fast-forward/pypy/translator/c/primitive.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/primitive.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/primitive.py Sun Jun 20 18:38:42 2010 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ CompositeOffset, ArrayLengthOffset, \ - GCHeaderOffset, GCREF + GCHeaderOffset, GCREF, AddressAsInt from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation from pypy.translator.c.support import cdecl, barebonearray @@ -61,6 +61,8 @@ name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) + elif isinstance(value, AddressAsInt): + return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r"%value) if value is None: Modified: pypy/branch/fast-forward/pypy/translator/c/src/address.h ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/src/address.h (original) +++ pypy/branch/fast-forward/pypy/translator/c/src/address.h Sun Jun 20 18:38:42 2010 @@ -16,5 +16,5 @@ #define OP_ADR_LT(x,y,r) r = ((x) < (y)) #define OP_ADR_GE(x,y,r) r = ((x) >= (y)) -#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x) -#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) +#define OP_CAST_ADR_TO_INT(x, mode, r) r = ((long)x) +#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x)) Modified: pypy/branch/fast-forward/pypy/translator/c/src/commondefs.h ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/src/commondefs.h (original) +++ pypy/branch/fast-forward/pypy/translator/c/src/commondefs.h Sun Jun 20 18:38:42 2010 @@ -82,5 +82,7 @@ #define Py_HUGE_VAL HUGE_VAL #ifdef _WIN32 +#ifndef MS_WINDOWS # define MS_WINDOWS /* a synonym */ #endif +#endif Modified: pypy/branch/fast-forward/pypy/translator/c/src/int.h ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/src/int.h (original) +++ pypy/branch/fast-forward/pypy/translator/c/src/int.h Sun Jun 20 18:38:42 2010 @@ -47,6 +47,14 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) +/* Implement INT_BETWEEN by optimizing for the common case where a and c + are constants (the 2nd subtraction below is then constant-folded), or + for the case of a == 0 (both subtractions are then constant-folded). + Note that the following line only works if a <= c in the first place, + which we assume is true. */ +#define OP_INT_BETWEEN(a,b,c,r) r = (((unsigned long)b - (unsigned long)a) \ + < ((unsigned long)c - (unsigned long)a)) + /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) Modified: pypy/branch/fast-forward/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/src/mem.h (original) +++ pypy/branch/fast-forward/pypy/translator/c/src/mem.h Sun Jun 20 18:38:42 2010 @@ -6,8 +6,7 @@ extern char __gcmapstart; extern char __gcmapend; extern char __gccallshapes; -extern void *__gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); #define __gcnoreorderhack __gcmapend /* The following pseudo-instruction is used by --gcrootfinder=asmgcc @@ -47,15 +46,13 @@ i == 0 ? (void*)&__gcmapstart : \ i == 1 ? (void*)&__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #else extern void* __gcmapstart; extern void* __gcmapend; extern char* __gccallshapes; -extern void* __gcrootanchor; -extern long pypy_asm_stackwalk(void*); +extern long pypy_asm_stackwalk(void*, void*); /* With the msvc Microsoft Compiler, the optimizer seems free to move any code (even asm) that involves local memory (registers and stack). @@ -82,7 +79,6 @@ i == 0 ? (void*)__gcmapstart : \ i == 1 ? (void*)__gcmapend : \ i == 2 ? (void*)&__gccallshapes : \ - i == 3 ? (void*)&__gcrootanchor : \ NULL #endif Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py Sun Jun 20 18:38:42 2010 @@ -221,13 +221,6 @@ res = f1() assert res == os.getcwd() -def test_strerror(): - def does_stuff(): - return os.strerror(2) - f1 = compile(does_stuff, []) - res = f1() - assert res == os.strerror(2) - def test_system(): def does_stuff(cmd): return os.system(cmd) Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/test/test_genc.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/test/test_genc.py Sun Jun 20 18:38:42 2010 @@ -144,10 +144,8 @@ assert f1() == '\x00' def test_runtime_type_info(): - S = GcStruct('s', ('is_actually_s1', Bool)) - S1 = GcStruct('s1', ('sub', S)) - attachRuntimeTypeInfo(S) - attachRuntimeTypeInfo(S1) + S = GcStruct('s', ('is_actually_s1', Bool), rtti=True) + S1 = GcStruct('s1', ('sub', S), rtti=True) def rtti_S(p): if p.is_actually_s1: return getRuntimeTypeInfo(S1) Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/test/test_lladdresses.py Sun Jun 20 18:38:42 2010 @@ -193,3 +193,42 @@ fc = compile(f, [int]) res = fc(42) assert res == 0 + +def test_cast_int_to_adr(): + S = lltype.Struct("S", ("x", lltype.Signed)) + s = lltype.malloc(S, immortal=True) + s.x = 42 + integer = cast_adr_to_int(cast_ptr_to_adr(s), mode="symbolic") + def f(n): + if n > 1: + i = integer + else: + i = 123 # nonsense, but never used + print "hello world" # prevent constant-folding + adr = cast_int_to_adr(i) + s = cast_adr_to_ptr(adr, lltype.Ptr(S)) + return s.x + fc = compile(f, [int]) + res = fc(5) + assert res == 42 + +def test_dict_of_addresses(): + TP = lltype.Struct('x') + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + + def f(i): + d = {} + d[cast_ptr_to_adr(a)] = 123 + d[cast_ptr_to_adr(b)] = 456 + if i > 5: + key = cast_ptr_to_adr(a) + else: + key = cast_ptr_to_adr(b) + return d[key] + + fc = compile(f, [int]) + res = fc(-77) + assert res == 456 + res = fc(77) + assert res == 123 Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_refcount.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/test/test_refcount.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/test/test_refcount.py Sun Jun 20 18:38:42 2010 @@ -130,9 +130,8 @@ def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: - S = lltype.GcStruct('S', ('x', lltype.Signed)) + S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/test/test_typed.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/test/test_typed.py Sun Jun 20 18:38:42 2010 @@ -79,11 +79,6 @@ nested_whiles = self.getcompiled(snippet.nested_whiles, [int, int]) assert nested_whiles(5,3) == '!!!!!' - def test_call_five(self): - call_five = self.getcompiled(snippet.call_five, [int]) - result = call_five() - assert result == [5] - def test_call_unpack_56(self): call_unpack_56 = self.getcompiled(snippet.call_unpack_56, []) result = call_unpack_56() @@ -116,13 +111,6 @@ assert fn(4) == 789 assert fn(5) == 101112 - def test_get_set_del_slice(self): - fn = self.getcompiled(snippet.get_set_del_slice, [list]) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - def test_type_conversion(self): # obfuscated test case specially for typer.insert_link_conversions() def type_conversion(n): Modified: pypy/branch/fast-forward/pypy/translator/driver.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/driver.py (original) +++ pypy/branch/fast-forward/pypy/translator/driver.py Sun Jun 20 18:38:42 2010 @@ -513,7 +513,12 @@ defines = cbuilder.DEBUG_DEFINES else: defines = {} - c_source_filename = cbuilder.generate_source(database, defines) + if self.exe_name is not None: + exe_name = self.exe_name % self.get_info() + else: + exe_name = None + c_source_filename = cbuilder.generate_source(database, defines, + exe_name=exe_name) self.log.info("written: %s" % (c_source_filename,)) if self.config.translation.dump_static_data_info: from pypy.translator.tool.staticsizereport import dump_static_data_info @@ -530,19 +535,20 @@ newexename = self.exe_name % self.get_info() if '/' not in newexename and '\\' not in newexename: newexename = './' + newexename - return mkexename(py.path.local(newexename)) + return py.path.local(newexename) def create_exe(self): """ Copy the compiled executable into translator/goal """ if self.exe_name is not None: - exename = mkexename(self.c_entryp) - newexename = self.compute_exe_name() + exename = self.c_entryp + newexename = mkexename(self.compute_exe_name()) shutil.copy(str(exename), str(newexename)) if self.cbuilder.shared_library_name is not None: soname = self.cbuilder.shared_library_name newsoname = newexename.new(basename=soname.basename) shutil.copy(str(soname), str(newsoname)) + self.log.info("copied: %s" % (newsoname,)) self.c_entryp = newexename self.log.info("created: %s" % (self.c_entryp,)) Modified: pypy/branch/fast-forward/pypy/translator/goal/targetpreimportedpypy.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/targetpreimportedpypy.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/targetpreimportedpypy.py Sun Jun 20 18:38:42 2010 @@ -3,7 +3,6 @@ import os, sys sys.setrecursionlimit(17000) -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy Modified: pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py Sun Jun 20 18:38:42 2010 @@ -2,7 +2,6 @@ import os, sys -from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy Modified: pypy/branch/fast-forward/pypy/translator/platform/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/platform/__init__.py (original) +++ pypy/branch/fast-forward/pypy/translator/platform/__init__.py Sun Jun 20 18:38:42 2010 @@ -5,6 +5,7 @@ import sys, py, os +from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_log log = py.log.Producer("platform") py.log.setconsumer("platform", ansi_log) @@ -62,9 +63,20 @@ def execute(self, executable, args=None, env=None, compilation_info=None): if env is None: env = os.environ.copy() - if compilation_info is not None: + else: + env = env.copy() + + # On Windows, %SystemRoot% must be present for most programs to start + if (os.name == 'nt' and + "SystemRoot" not in env and + "SystemRoot" in os.environ): + env["SystemRoot"] = os.environ["SystemRoot"] + + # Set LD_LIBRARY_PATH on posix platforms + if os.name == 'posix' and compilation_info is not None: env['LD_LIBRARY_PATH'] = ':'.join( [str(i) for i in compilation_info.library_dirs]) + returncode, stdout, stderr = _run_subprocess(str(executable), args, env) return ExecutionResult(returncode, stdout, stderr) @@ -112,6 +124,18 @@ for line in stderr.splitlines(): log.WARNING(line) + def _make_response_file(self, prefix): + """Creates a temporary file with the specified prefix, + and returns its name""" + # Build unique filename + num = 0 + while 1: + response_file = udir.join('%s%i' % (prefix, num)) + num += 1 + if not response_file.check(): + break + return response_file + def _preprocess_include_dirs(self, include_dirs): return include_dirs @@ -133,9 +157,15 @@ library_dirs = self._libdirs(library_dirs) libraries = self._libs(eci.libraries) link_files = self._linkfiles(eci.link_files) - return (library_dirs + self.link_flags + + export_flags = self._exportsymbols_link_flags(eci) + return (library_dirs + self.link_flags + export_flags + link_files + list(eci.link_extra) + libraries) + def _exportsymbols_link_flags(self, eci): + if eci.export_symbols: + raise ValueError("This platform does not support export symbols") + return [] + def _finish_linking(self, ofiles, eci, outputfilename, standalone): if outputfilename is None: outputfilename = ofiles[0].purebasename Modified: pypy/branch/fast-forward/pypy/translator/platform/darwin.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/platform/darwin.py (original) +++ pypy/branch/fast-forward/pypy/translator/platform/darwin.py Sun Jun 20 18:38:42 2010 @@ -56,6 +56,17 @@ include_dirs = self._includedirs(eci.include_dirs) return (args + frameworks + include_dirs) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("_%s\n" % (sym,)) + f.close() + return ["-Wl,-exported_symbols_list,%s" % (response_file,)] + class Darwin_i386(Darwin): name = "darwin_i386" link_flags = ['-arch', 'i386', '-mmacosx-version-min=10.4'] Modified: pypy/branch/fast-forward/pypy/translator/platform/posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/platform/posix.py (original) +++ pypy/branch/fast-forward/pypy/translator/platform/posix.py Sun Jun 20 18:38:42 2010 @@ -37,9 +37,21 @@ return oname def _link_args_from_eci(self, eci, standalone): - eci = eci.convert_exportsymbols_to_file() return Platform._link_args_from_eci(self, eci, standalone) + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("dynamic-symbols-") + f = response_file.open("w") + f.write("{\n") + for sym in eci.export_symbols: + f.write("%s;\n" % (sym,)) + f.write("};") + f.close() + return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] + def _link(self, cc, ofiles, link_args, standalone, exe_name): args = [str(ofile) for ofile in ofiles] + link_args args += ['-o', str(exe_name)] @@ -61,7 +73,6 @@ def gen_makefile(self, cfiles, eci, exe_name=None, path=None, shared=False): - eci = eci.convert_exportsymbols_to_file() cfiles = [py.path.local(f) for f in cfiles] cfiles += [py.path.local(f) for f in eci.separate_module_files] @@ -72,11 +83,15 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + linkflags += self._exportsymbols_link_flags(eci) + if shared: libname = exe_name.new(ext='').basename target_name = 'lib' + exe_name.new(ext=self.so_ext).basename @@ -133,6 +148,7 @@ if shared: m.definition('SHARED_IMPORT_LIB', libname), + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo "' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' Modified: pypy/branch/fast-forward/pypy/translator/platform/test/test_platform.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/platform/test/test_platform.py (original) +++ pypy/branch/fast-forward/pypy/translator/platform/test/test_platform.py Sun Jun 20 18:38:42 2010 @@ -113,7 +113,7 @@ def test_environment_inheritance(self): # make sure that environment is inherited cmd = 'import os; print os.environ["_SOME_VARIABLE_%d"]' - res = self.platform.execute('python', ['-c', cmd % 1], + res = self.platform.execute(sys.executable, ['-c', cmd % 1], env={'_SOME_VARIABLE_1':'xyz'}) assert 'xyz' in res.out os.environ['_SOME_VARIABLE_2'] = 'zyz' Modified: pypy/branch/fast-forward/pypy/translator/platform/windows.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/platform/windows.py (original) +++ pypy/branch/fast-forward/pypy/translator/platform/windows.py Sun Jun 20 18:38:42 2010 @@ -139,8 +139,18 @@ def _link_args_from_eci(self, eci, standalone): # Windows needs to resolve all symbols even for DLLs - args = super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) - return args + ['/EXPORT:%s' % symbol for symbol in eci.export_symbols] + return super(MsvcPlatform, self)._link_args_from_eci(eci, standalone=True) + + def _exportsymbols_link_flags(self, eci): + if not eci.export_symbols: + return [] + + response_file = self._make_response_file("exported_symbols_") + f = response_file.open("w") + for sym in eci.export_symbols: + f.write("/EXPORT:%s\n" % (sym,)) + f.close() + return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): oname = cfile.new(ext='obj') @@ -179,7 +189,7 @@ # Microsoft compilers write compilation errors to stdout stderr = stdout + stderr errorfile = outname.new(ext='errors') - errorfile.write(stderr) + errorfile.write(stderr, mode='wb') stderrlines = stderr.splitlines() for line in stderrlines: log.ERROR(line) @@ -198,18 +208,22 @@ if exe_name is None: exe_name = cfiles[0].new(ext=self.exe_ext) + else: + exe_name = exe_name.new(ext=self.exe_ext) m = NMakefile(path) m.exe_name = exe_name m.eci = eci - linkflags = self.link_flags + linkflags = self.link_flags[:] if shared: linkflags = self._args_for_shared(linkflags) + [ '/EXPORT:$(PYPY_MAIN_FUNCTION)'] + linkflags += self._exportsymbols_link_flags(eci) if shared: - so_name = exe_name.new(ext=self.so_ext) + so_name = exe_name.new(purebasename='lib' + exe_name.purebasename, + ext=self.so_ext) target_name = so_name.basename else: target_name = exe_name.basename @@ -243,6 +257,7 @@ ('LDFLAGSEXTRA', list(eci.link_extra)), ('CC', self.cc), ('CC_LINK', self.link), + ('LINKFILES', eci.link_files), ('MASM', self.masm), ] @@ -262,19 +277,22 @@ '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS)') else: m.rule('$(TARGET)', '$(OBJECTS)', - ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) if shared: - m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename), + m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename) + m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup") m.rule('main.c', '', 'echo ' 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); ' 'int main(int argc, char* argv[]) ' '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@') m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'], - '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@') + ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFESTFILE:$*.manifest', + 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', + ]) return m @@ -319,6 +337,7 @@ shared_only = [] cflags = ['-O3'] link_flags = [] + exe_ext = 'exe' so_ext = 'dll' def __init__(self, cc=None): Modified: pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/test/test_sandbox.py Sun Jun 20 18:38:42 2010 @@ -145,7 +145,9 @@ g = pipe.stdin f = pipe.stdout expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GENERATIONGC_NURSERY",), None) - expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), OSError(5232, "xyz")) + if sys.platform == 'linux2': # on Mac, uses another (sandboxsafe) approach + expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), + OSError(5232, "xyz")) g.close() tail = f.read() f.close() Modified: pypy/branch/fast-forward/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/tool/cbuild.py (original) +++ pypy/branch/fast-forward/pypy/translator/tool/cbuild.py Sun Jun 20 18:38:42 2010 @@ -260,34 +260,6 @@ d['separate_module_files'] += tuple(files) return ExternalCompilationInfo(**d) - def convert_exportsymbols_to_file(self): - if not self.export_symbols: - return self - num = 0 - while 1: - file_name = udir.join('dynamic-symbols-%i' % num) - num += 1 - if not file_name.check(): - break - - # XXX this logic should be moved to translator/platform/*.py - d = self._copy_attributes() - f = file_name.open("w") - if host.name.startswith('darwin'): - for sym in self.export_symbols: - f.write("_%s\n" % (sym,)) - d['link_extra'] += ("-Wl,-exported_symbols_list,"+str(file_name), ) - else: - f.write("{\n") - for sym in self.export_symbols: - f.write("%s;\n" % (sym,)) - f.write("};") - d['link_extra'] += ("-Wl,--export-dynamic,--version-script=" + str(file_name), ) - f.close() - d['export_symbols'] = () - return ExternalCompilationInfo(**d) - - def get_module_files(self): d = self._copy_attributes() files = d['separate_module_files'] Modified: pypy/branch/fast-forward/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/fast-forward/pypy/translator/tool/make_dot.py Sun Jun 20 18:38:42 2010 @@ -152,7 +152,7 @@ shape = "octagon" if block.exitswitch is not None: - lines.append("exitswitch: %s" % block.exitswitch) + lines.append("exitswitch: %s" % (block.exitswitch,)) iargs = " ".join(map(repr, block.inputargs)) if self.VERBOSE: Modified: pypy/branch/fast-forward/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/branch/fast-forward/pypy/translator/tool/test/test_cbuild.py Sun Jun 20 18:38:42 2010 @@ -71,17 +71,6 @@ e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e - def test_convert_sources_to_c_files(self): - eci = ExternalCompilationInfo( - export_symbols=("foo", ) - ) - neweci = eci.convert_exportsymbols_to_file() - le = neweci.link_extra[-1] - assert "foo;" in file(le.rsplit("=", 1)[1]).read() - e = ExternalCompilationInfo() - assert e.convert_exportsymbols_to_file() is e - - def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' Modified: pypy/branch/fast-forward/pypy/translator/translator.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/translator.py (original) +++ pypy/branch/fast-forward/pypy/translator/translator.py Sun Jun 20 18:38:42 2010 @@ -7,7 +7,6 @@ import autopath, os, sys, types, copy from pypy.translator import simplify -from pypy.objspace.flow.objspace import FlowObjSpace from pypy.objspace.flow.model import FunctionGraph, checkgraph, Block from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func @@ -67,6 +66,7 @@ else: if self.config.translation.verbose: log.start(nice_repr_for_func(func)) + from pypy.objspace.flow.objspace import FlowObjSpace space = FlowObjSpace(self.flowconfig) if self.annotator: # ZZZ From arigo at codespeak.net Sun Jun 20 18:53:27 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 20 Jun 2010 18:53:27 +0200 (CEST) Subject: [pypy-svn] r75480 - in pypy/branch/multijit-4/pypy/rlib/rsre: . test Message-ID: <20100620165327.DA7FC282B9E@codespeak.net> Author: arigo Date: Sun Jun 20 18:53:26 2010 New Revision: 75480 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py Log: Whack whack whack. Still modest improvements, although in the example I am trying I managed to remove most mallocs. Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/rsre_char.py Sun Jun 20 18:53:26 2010 @@ -155,11 +155,9 @@ SET_OK = -1 SET_NOT_OK = -2 -def check_charset(char_code, context): +def check_charset(char_code, pattern_codes, index): """Checks whether a character matches set of arbitrary length. Currently assumes the set starts at the first member of pattern_codes.""" - pattern_codes = context.pattern_codes - index = context.code_position negated = SET_OK while index >= 0: opcode = pattern_codes[index] Modified: pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/rsre_core.py Sun Jun 20 18:53:26 2010 @@ -21,7 +21,22 @@ class StateMixin(object): def reset(self): - self.string_position = self.start + pass + + def search(self, pattern_codes): + return search(self, pattern_codes) + + def match(self, pattern_codes): + return match(self, pattern_codes) + + +class DynamicState(object): + + def __init__(self, staticstate, start, end, string_position): + self.staticstate = staticstate + self.start = start + self.end = end + self.string_position = string_position self.marks = [0, 0, 0, 0] self.lastindex = -1 self.marks_count = 0 @@ -32,15 +47,9 @@ # with x and y saved indices to allow pops. self.saved_marks = [] self.saved_marks_top = 0 - self.context_stack = [] + self.top_context = None self.repeat = None - def search(self, pattern_codes): - return search(self, pattern_codes) - - def match(self, pattern_codes): - return match(self, pattern_codes) - def create_regs(self, group_count): """Creates a tuple of index pairs representing matched groups, a format that's convenient for SRE_Match.""" @@ -57,6 +66,9 @@ regs.append((start, end)) return regs + def lower(self, char): + return self.staticstate.lower(char) + def set_mark(self, mark_nr, position): assert mark_nr >= 0 if mark_nr & 1: @@ -81,17 +93,22 @@ def marks_push(self): # Create in saved_marks: [......, m1,..,mn,lastindex,p, ...........] # ^p ^newsize - p = self.saved_marks_top - n = self.marks_count + newsize = self._marks_push(self.saved_marks_top, self.marks_count, + self.saved_marks, self.marks, + self.lastindex) + self.saved_marks_top = newsize + + @staticmethod + def _marks_push(p, n, saved_marks, marks, lastindex): assert p >= 0 newsize = p + n + 2 - while len(self.saved_marks) < newsize: - self.saved_marks.append(-1) + while len(saved_marks) < newsize: + saved_marks.append(-1) for i in range(n): - self.saved_marks[p+i] = self.marks[i] - self.saved_marks[p+n] = self.lastindex - self.saved_marks[p+n+1] = p - self.saved_marks_top = newsize + saved_marks[p+i] = marks[i] + saved_marks[p+n] = lastindex + saved_marks[p+n+1] = p + return newsize def marks_pop(self): p0 = self.marks_pop_keep() @@ -106,11 +123,15 @@ n = p1 - p0 assert p0 >= 0 and n >= 0 self.lastindex = self.saved_marks[p1] - for i in range(n): - self.marks[i] = self.saved_marks[p0+i] + self._marks_pop_keep(self.marks, self.saved_marks, n, p0) self.marks_count = n return p0 + @staticmethod + def _marks_pop_keep(marks, saved_marks, n, p0): + for i in range(n): + marks[i] = saved_marks[p0+i] + def marks_pop_discard(self): p0 = self.saved_marks[self.saved_marks_top-1] self.saved_marks_top = p0 @@ -118,14 +139,16 @@ class MatchContext(rsre_char.MatchContextBase): - def __init__(self, state, pattern_codes, offset=0): + def __init__(self, state, pattern_codes, offset=0, prev_context=None): self.state = state + self.staticstate = state.staticstate self.pattern_codes = pattern_codes self.string_position = state.string_position self.code_position = offset self.has_matched = self.UNDECIDED self.backup = [] self.resume_at_opcode = -1 + self.prev_context = prev_context def push_new_context(self, pattern_offset): """Creates a new child context of this context and pushes it on the @@ -133,8 +156,9 @@ start interpreting from.""" offset = self.code_position + pattern_offset assert offset >= 0 - child_context = MatchContext(self.state, self.pattern_codes, offset) - self.state.context_stack.append(child_context) + child_context = MatchContext(self.state, self.pattern_codes, offset, + self.state.top_context) + self.state.top_context = child_context self.child_context = child_context return child_context @@ -150,7 +174,7 @@ return values def peek_char(self, peek=0): - return self.state.get_char_ord(self.string_position + peek) + return self.staticstate.get_char_ord(self.string_position + peek) def skip_char(self, skip_count): self.string_position = self.string_position + skip_count @@ -192,18 +216,20 @@ #### Main opcode dispatch loop -def search(state, pattern_codes): +def search(staticstate, pattern_codes): flags = 0 if pattern_codes[0] == OPCODE_INFO: # optimization info block # <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> if pattern_codes[2] & SRE_INFO_PREFIX and pattern_codes[5] > 1: - return fast_search(state, pattern_codes) + return fast_search(staticstate, pattern_codes) flags = pattern_codes[2] offset = pattern_codes[1] + 1 assert offset >= 0 #pattern_codes = pattern_codes[offset:] + raise NotImplementedError("XXX") + string_position = state.start while string_position <= state.end: state.reset() @@ -215,10 +241,10 @@ from pypy.rlib.jit import JitDriver, unroll_safe rsrejitdriver = JitDriver(greens=['i', 'overlap_offset', 'pattern_codes'], - reds=['string_position', 'end', 'state'], + reds=['string_position', 'end', 'staticstate'], can_inline=lambda *args: False) -def fast_search(state, pattern_codes): +def fast_search(staticstate, pattern_codes): """Skips forward in a string as fast as possible using information from an optimization info block.""" # pattern starts with a known prefix @@ -227,8 +253,8 @@ overlap_offset = 7 + prefix_len - 1 assert overlap_offset >= 0 i = 0 - string_position = state.string_position - end = state.end + string_position = staticstate.start + end = staticstate.end while string_position < end: while True: rsrejitdriver.can_enter_jit( @@ -236,16 +262,16 @@ i=i, string_position=string_position, end=end, - state=state, + staticstate=staticstate, overlap_offset=overlap_offset) rsrejitdriver.jit_merge_point( pattern_codes=pattern_codes, i=i, string_position=string_position, end=end, - state=state, + staticstate=staticstate, overlap_offset=overlap_offset) - char_ord = state.get_char_ord(string_position) + char_ord = staticstate.get_char_ord(string_position) if char_ord != pattern_codes[7+i]: if i == 0: break @@ -257,21 +283,24 @@ if i == prefix_len: # found a potential match prefix_skip = pattern_codes[6] - state.start = string_position + 1 - prefix_len - state.string_position = string_position + 1 \ - - prefix_len + prefix_skip + state = DynamicState( + staticstate, + start = string_position + 1 - prefix_len, + end = staticstate.end, + string_position = (string_position + 1 + - prefix_len + prefix_skip)) flags = pattern_codes[2] if flags & SRE_INFO_LITERAL: - return True # matched all of pure literal pattern + return state # matched all of pure literal pattern pattern_offset = pattern_codes[1] + 1 start = pattern_offset + 2 * prefix_skip assert start >= 0 if match(state, pattern_codes, start): - return True + return state i = pattern_codes[overlap_offset + i] break string_position += 1 - return False + return None @unroll_safe def match(state, pattern_codes, pstart=0): @@ -283,16 +312,16 @@ if state.end - state.string_position < pattern_codes[pstart+3]: return False pstart += pattern_codes[pstart+1] + 1 - state.context_stack.append(MatchContext(state, pattern_codes, pstart)) + state.top_context = MatchContext(state, pattern_codes, pstart) has_matched = MatchContext.UNDECIDED - while len(state.context_stack) > 0: - context = state.context_stack[-1] + while state.top_context is not None: + context = state.top_context if context.has_matched == context.UNDECIDED: has_matched = dispatch_loop(context) else: has_matched = context.has_matched if has_matched != context.UNDECIDED: # don't pop if context isn't done - state.context_stack.pop() + state.top_context = context.prev_context return has_matched == MatchContext.MATCHED @unroll_safe @@ -417,6 +446,7 @@ char_code = ctx.peek_char() if ignore: char_code = ctx.state.lower(char_code) + raise NotImplementedError("XXX") if not rsre_char.check_charset(char_code, ctx): ctx.has_matched = ctx.NOT_MATCHED return @@ -499,7 +529,19 @@ # Initialize the actual backtracking if count >= mincount: - count = quickly_skip_unmatchable_positions(ctx, count, mincount) + # + nextidx = ctx.peek_code(1) + if ctx.peek_code(nextidx + 1) == OPCODE_LITERAL: + # tail starts with a literal. skip positions where + # the rest of the pattern cannot possibly match + chr = ctx.peek_code(nextidx + 2) + sp1 = ctx.string_position + sp2 = quickly_skip_unmatchable_positions(chr, sp1, + count - mincount, + ctx.staticstate) + ctx.string_position = sp2 + count -= (sp1 - sp2) + # if count >= mincount: ctx.state.string_position = ctx.string_position ctx.push_new_context(ctx.peek_code(1) + 1) @@ -512,22 +554,17 @@ ctx.has_matched = ctx.NOT_MATCHED return True -def quickly_skip_unmatchable_positions(ctx, count, mincount): - # this is only an optimization - nextidx = ctx.peek_code(1) - if ctx.peek_code(nextidx + 1) == OPCODE_LITERAL: - # tail starts with a literal. skip positions where - # the rest of the pattern cannot possibly match - chr = ctx.peek_code(nextidx + 2) - if ctx.at_end(): - ctx.skip_char(-1) - count -= 1 - while count >= mincount: - if ctx.peek_char() == chr: - break - ctx.skip_char(-1) - count -= 1 - return count +def quickly_skip_unmatchable_positions(chr, string_position, reduce_up_to, + staticstate): + string_position_min = string_position - reduce_up_to + assert string_position_min >= 0 + if string_position == staticstate.end: + string_position -= 1 + while string_position >= string_position_min: + if staticstate.get_char_ord(string_position) == chr: + break + string_position -= 1 + return string_position def op_min_repeat_one(ctx): # match repeated sequence (minimizing) @@ -803,7 +840,7 @@ return True while group_start < group_end: new_char = ctx.peek_char() - old_char = ctx.state.get_char_ord(group_start) + old_char = ctx.staticstate.get_char_ord(group_start) if ctx.at_end() or (not ignore and old_char != new_char) \ or (ignore and ctx.state.lower(old_char) != ctx.state.lower(new_char)): ctx.has_matched = ctx.NOT_MATCHED @@ -929,27 +966,30 @@ ##### count_repetitions dispatch -def general_cr_in(ctx, maxcount, ignore): - code_position = ctx.code_position +def general_cr_in(maxcount, ignore, pattern_codes, code_position, + staticstate, string_position): + code_position += 6 # set op pointer to the set code count = 0 while count < maxcount: - ctx.code_position = code_position - ctx.skip_code(6) # set op pointer to the set code - char_code = ctx.peek_char(count) + char_code = staticstate.get_char_ord(string_position + count) if ignore: - char_code = ctx.state.lower(char_code) - if not rsre_char.check_charset(char_code, ctx): + char_code = staticstate.lower(char_code) + if not rsre_char.check_charset(char_code, pattern_codes, + code_position): break count += 1 - ctx.code_position = code_position return count -general_cr_in._annspecialcase_ = 'specialize:arg(2)' +general_cr_in._annspecialcase_ = 'specialize:arg(1)' def cr_in(ctx, maxcount): - return general_cr_in(ctx, maxcount, False) + return general_cr_in(maxcount, False, + ctx.pattern_codes, ctx.code_position, + ctx.staticstate, ctx.string_position) def cr_in_ignore(ctx, maxcount): - return general_cr_in(ctx, maxcount, True) + return general_cr_in(maxcount, True, + ctx.pattern_codes, ctx.code_position, + ctx.staticstate, ctx.string_position) def cr_any(ctx, maxcount): count = 0 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/test/targetrsre.py Sun Jun 20 18:53:26 2010 @@ -32,9 +32,9 @@ while True: state = rsre.SimpleStringState(data, p) res = state.search(r) - if not res: + if res is None: break - groups = state.create_regs(1) + groups = res.create_regs(1) matchstart, matchstop = groups[1] assert 0 <= matchstart <= matchstop print '%s: %s' % (filename, data[matchstart:matchstop]) Modified: pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py Sun Jun 20 18:53:26 2010 @@ -24,8 +24,8 @@ r_code1 = self.get_code(r'\s*(.*?)') state = rsre.SimpleStringState("foo abcdef") res = state.search(r_code1) - assert res is True - groups = state.create_regs(1) + assert res is not None + groups = res.create_regs(1) assert groups[0] == (3, 29) assert groups[1] == (18, 21) From jcreigh at codespeak.net Tue Jun 22 01:01:35 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 22 Jun 2010 01:01:35 +0200 (CEST) Subject: [pypy-svn] r75483 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100621230135.F1302282B9D@codespeak.net> Author: jcreigh Date: Tue Jun 22 01:01:33 2010 New Revision: 75483 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Log: in some cases remember the value of the scratch register and output offsets based on it instead of loading a new 64-bit immediate Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Tue Jun 22 01:01:33 2010 @@ -447,6 +447,7 @@ adr_stackadjust = self._call_header() tmp = X86RegisterManager.all_regs[0] xmmtmp = X86XMMRegisterManager.all_regs[0] + self.mc._mc.begin_reuse_scratch_register() for i in range(len(nonfloatlocs)): loc = nonfloatlocs[i] if loc is None: @@ -478,6 +479,7 @@ self.mc.MOVSD(xmmtmp, heap(adr)) assert isinstance(loc, StackLoc) self.mc.MOVSD_bx(loc.value, xmmtmp.value) + self.mc._mc.end_reuse_scratch_register() return adr_stackadjust def dump(self, text): @@ -1444,6 +1446,7 @@ def generate_failure(self, fail_index, locs, exc, locs_are_ref): mc = self.mc + mc._mc.begin_reuse_scratch_register() for i in range(len(locs)): loc = locs[i] if isinstance(loc, RegLoc): @@ -1470,6 +1473,7 @@ adr = self.fail_boxes_int.get_addr_for_num(i) mc.MOV(eax, loc) mc.MOV(heap(adr), eax) + mc._mc.end_reuse_scratch_register() # we call a provided function that will # - call our on_leave_jitted_hook which will mark Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Tue Jun 22 01:01:33 2010 @@ -158,6 +158,10 @@ class LocationCodeBuilder(object): _mixin_ = True + _reuse_scratch_register = False + _scratch_register_known = False + _scratch_register_value = 0 + def _binaryop(name): def INSN(self, loc1, loc2): code1 = loc1.location_code() @@ -188,17 +192,17 @@ else: assert False, "a" elif self.WORD == 8 and possible_code1 == 'j': - self.MOV_ri(X86_64_SCRATCH_REG.value, val1) + reg_offset = self._addr_as_reg_offset(val1) methname = name + "_" + "m" + possible_code2 if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)((X86_64_SCRATCH_REG.value, 0), val2) + getattr(self, methname)(reg_offset, val2) else: assert False, "b" elif self.WORD == 8 and possible_code2 == 'j': - self.MOV_ri(X86_64_SCRATCH_REG.value, val2) + reg_offset = self._addr_as_reg_offset(val2) methname = name + "_" + possible_code1 + "m" if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)(val1, (X86_64_SCRATCH_REG.value, 0)) + getattr(self, methname)(val1, reg_offset) else: assert False, "c" else: @@ -236,6 +240,36 @@ return INSN + def _addr_as_reg_offset(self, addr): + # Encodes a (64-bit) address as an offset from the scratch register. + # If we are within a "reuse_scratch_register" block, we remember the + # last value we loaded to the scratch register and encode the address + # as an offset from that if we can + if self._scratch_register_known: + offset = addr - self._scratch_register_value + if rx86.fits_in_32bits(offset): + return (X86_64_SCRATCH_REG.value, offset) + # else: fall through + + if self._reuse_scratch_register: + self._scratch_register_known = True + self._scratch_register_value = addr + + self.MOV_ri(X86_64_SCRATCH_REG.value, addr) + return (X86_64_SCRATCH_REG.value, 0) + + def begin_reuse_scratch_register(self): + # Flag the beginning of a block where it is okay to reuse the value + # of the scratch register. In theory we shouldn't have to do this if + # we were careful to mark all possible targets of a jump or call, and + # "forget" the value of the scratch register at those positions, but + # for now this seems safer. + self._reuse_scratch_register = True + + def end_reuse_scratch_register(self): + self._reuse_scratch_register = False + self._scratch_register_known = False + AND = _binaryop('AND') OR = _binaryop('OR') XOR = _binaryop('XOR') Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Tue Jun 22 01:01:33 2010 @@ -1,10 +1,15 @@ from pypy.jit.backend.x86.regloc import * -from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, assert_encodes_as +from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as +from pypy.jit.backend.x86.assembler import heap class LocationCodeBuilder32(CodeBuilder32, LocationCodeBuilder): pass +class LocationCodeBuilder64(CodeBuilder64, LocationCodeBuilder): + pass + cb32 = LocationCodeBuilder32 +cb64 = LocationCodeBuilder64 def test_mov_16(): assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') @@ -13,3 +18,21 @@ def test_cmp_16(): assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') + +def test_reuse_scratch_register(): + base_addr = 0xFEDCBA9876543210 + cb = LocationCodeBuilder64() + cb.begin_reuse_scratch_register() + cb.MOV(ecx, heap(base_addr)) + cb.MOV(ecx, heap(base_addr + 8)) + cb.end_reuse_scratch_register() + + expected_instructions = ( + # mov r11, 0xFEDCBA9876543210 + '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE' + + # mov rcx, [r11] + '\x49\x8B\x0B' + + # mov rcx, [r11+8] + '\x49\x8B\x4B\x08' + ) + assert cb.getvalue() == expected_instructions From getxsick at codespeak.net Tue Jun 22 01:47:06 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 01:47:06 +0200 (CEST) Subject: [pypy-svn] r75484 - in pypy/branch/fast-ctypes/pypy: module/jitffi module/jitffi/test rlib Message-ID: <20100621234706.A3E4E282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 01:47:04 2010 New Revision: 75484 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: ok, module/jitffi seems to work now...for specific cases (e.g. only ints) at least one test passes :-) this check in is a bit messy as i have some problems to get it workable. need to clean it up a bit and add other functionality Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 01:47:04 2010 @@ -1,18 +1,66 @@ +from pypy.rlib import rdynload +from pypy.jit.backend.x86.runner import CPU from pypy.rlib import rjitffi from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import wrap_oserror from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef +class W_Lib(Wrappable): + def __init__(self, space, name): + try: + self.handler = rdynload.dlopen(name) + except rdynload.DLOpenError, e: + raise OSError('%s: %s', name, e.msg or 'unspecified error') + + self.space = space + +def descr_new_lib(space, w_type, name): + try: + return space.wrap(W_Lib(space, name)) + except OSError, e: + raise wrap_oserror(space, e) +descr_new_lib.unwrap_spec = [ObjSpace, W_Root, str] + +W_Lib.typedef = TypeDef( + 'Lib', + __new__ = interp2app(descr_new_lib) +) + +class W_Get(Wrappable, rjitffi._Get): + def __init__(self, space, cpu, lib, func, args_type, res_type='void'): + self.space = space + rjitffi._Get.__init__(self, cpu, lib, func, args_type, res_type) + + def call_w(self, w_args): + args_w = [ self.space.int_w(w_x) for w_x in self.space.listview(w_args) ] # XXX only int! + return self.space.wrap(self.call(args_w)) + + +def descr_new_get(space, w_type, cpu, lib, func, args_type, res_type): + try: + return space.wrap(W_Get(space, w_type, cpu, lib, func, args_type, res_type)) + except OSError, e: + raise wrap_oserror(space, e) +descr_new_get.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root, str, W_Root, str] + +W_Get.typedef = TypeDef( + 'Get', + #__new__ = interp2app(descr_new_get) + call = interp2app(W_Get.call_w, unwrap_spec=['self', W_Root]) +) + class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - rjitffi.CDLL.__init__(self, name) + self.lib = space.wrap(W_Lib(self.space, name)) + self.name = name + self.cpu = CPU(None, None) def get_w(self, func, w_args_type, res_type='void'): args_type_w = [ self.space.str_w(w_x) for w_x in self.space.listview(w_args_type) ] - return self.space.wrap(self.get(func, args_type_w, res_type)) + return self.space.wrap(W_Get(self.space, self.cpu, self.space.wrap(self.lib), func, args_type_w, res_type)) def descr_new_cdll(space, w_type, name): try: Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 01:47:04 2010 @@ -65,7 +65,7 @@ lib = jitffi.CDLL(self.lib_name) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 3 == func.call(1,2) + assert 3 == func.call([1,2]) func = lib.get('add_integers', ['int', 'int'], 'int') assert 1 == func.call(-1,2) func = lib.get('add_integers', ['int', 'int'], 'int') Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 01:47:04 2010 @@ -25,7 +25,7 @@ self.args_type = args_type self.res_type = res_type self.cpu = cpu - self.lib = lib + self.lib = lib.handler if self.res_type == 'int': self.bres = BoxInt() From getxsick at codespeak.net Tue Jun 22 02:08:16 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 02:08:16 +0200 (CEST) Subject: [pypy-svn] r75485 - pypy/branch/fast-ctypes/pypy/rlib Message-ID: <20100622000816.6765F282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 02:08:14 2010 New Revision: 75485 Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: Ops. Somehow i undo the last change and the last commit was incomplete. Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 02:08:14 2010 @@ -63,7 +63,7 @@ FUNC = deref(FPTR) self.calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) - def call(self, *func_args): + def call(self, func_args): bargs = [] for tp, value in zip(self.args_type, func_args): if tp == 'int': From getxsick at codespeak.net Tue Jun 22 02:27:10 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 02:27:10 +0200 (CEST) Subject: [pypy-svn] r75486 - in pypy/branch/fast-ctypes/pypy/module/jitffi: . test Message-ID: <20100622002710.DF063282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 02:27:09 2010 New Revision: 75486 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: module.jitffi can be used for other argument for now some limitations: - only int and float are supported - all arguments have to be the same type Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 02:27:09 2010 @@ -2,7 +2,7 @@ from pypy.jit.backend.x86.runner import CPU from pypy.rlib import rjitffi from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable -from pypy.interpreter.error import wrap_oserror +from pypy.interpreter.error import OperationError, wrap_oserror from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef @@ -32,8 +32,17 @@ self.space = space rjitffi._Get.__init__(self, cpu, lib, func, args_type, res_type) - def call_w(self, w_args): - args_w = [ self.space.int_w(w_x) for w_x in self.space.listview(w_args) ] # XXX only int! + def call_w(self, space, w_args): + if self.args_type[0] == 'int': + args_w = [ space.int_w(w_x) for w_x in space.listview(w_args) ] + elif self.args_type[0] == 'float': + args_w = [ space.float_w(w_x) for w_x in space.listview(w_args) ] + else: + raise OperationError( + space.w_TypeError, + space.wrap('Unsupported type of argument: %s' + % self.args_type[0])) + return self.space.wrap(self.call(args_w)) @@ -47,7 +56,7 @@ W_Get.typedef = TypeDef( 'Get', #__new__ = interp2app(descr_new_get) - call = interp2app(W_Get.call_w, unwrap_spec=['self', W_Root]) + call = interp2app(W_Get.call_w, unwrap_spec=['self', ObjSpace, W_Root]) ) class W_CDLL(Wrappable, rjitffi.CDLL): Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 02:27:09 2010 @@ -67,15 +67,15 @@ func = lib.get('add_integers', ['int', 'int'], 'int') assert 3 == func.call([1,2]) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 1 == func.call(-1,2) + assert 1 == func.call([-1,2]) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 0 == func.call(0,0) + assert 0 == func.call([0,0]) func = lib.get('max3', ['int', 'int', 'int'], 'int') - assert 8 == func.call(2, 8, 3) + assert 8 == func.call([2, 8, 3]) func = lib.get('add_floats', ['float', 'float'], 'float') - assert 2.7 == func.call(1.2, 1.5) + assert 2.7 == func.call([1.2, 1.5]) def test_get_void(self): import jitffi From getxsick at codespeak.net Tue Jun 22 02:47:06 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 02:47:06 +0200 (CEST) Subject: [pypy-svn] r75487 - in pypy/branch/fast-ctypes/pypy: module/jitffi module/jitffi/test rlib Message-ID: <20100622004706.41674282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 02:47:04 2010 New Revision: 75487 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: more tests pass. fix a problem with empty list of arguments for the calling function. Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 02:47:04 2010 @@ -32,18 +32,21 @@ self.space = space rjitffi._Get.__init__(self, cpu, lib, func, args_type, res_type) - def call_w(self, space, w_args): - if self.args_type[0] == 'int': - args_w = [ space.int_w(w_x) for w_x in space.listview(w_args) ] - elif self.args_type[0] == 'float': - args_w = [ space.float_w(w_x) for w_x in space.listview(w_args) ] + def call_w(self, space, w_args=None): + if space.is_w(w_args, space.w_None): + return space.wrap(self.call()) else: - raise OperationError( - space.w_TypeError, - space.wrap('Unsupported type of argument: %s' - % self.args_type[0])) + if self.args_type[0] == 'int': + args_w = [ space.int_w(w_x) for w_x in space.listview(w_args) ] + elif self.args_type[0] == 'float': + args_w = [ space.float_w(w_x) for w_x in space.listview(w_args) ] + else: + raise OperationError( + space.w_TypeError, + space.wrap('Unsupported type of argument: %s' + % self.args_type[0])) - return self.space.wrap(self.call(args_w)) + return space.wrap(self.call(args_w)) def descr_new_get(space, w_type, cpu, lib, func, args_type, res_type): Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 02:47:04 2010 @@ -85,9 +85,9 @@ assert 1 == func.call() func = lib.get('return_void', ['int', 'int'], 'void') - assert func.call(1, 2) is None + assert func.call([1, 2]) is None func = lib.get('return_void', ['int', 'int']) - assert func.call(1, 2) is None + assert func.call([1, 2]) is None def test_undefined_func(self): import jitffi Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 02:47:04 2010 @@ -63,7 +63,10 @@ FUNC = deref(FPTR) self.calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) - def call(self, func_args): + def call(self, func_args=None): + if func_args is None: + func_args = [] + bargs = [] for tp, value in zip(self.args_type, func_args): if tp == 'int': From getxsick at codespeak.net Tue Jun 22 03:56:05 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 03:56:05 +0200 (CEST) Subject: [pypy-svn] r75488 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100622015605.9FF87282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 03:56:03 2010 New Revision: 75488 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Log: use super.__init__ to reduce some code Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 03:56:03 2010 @@ -1,5 +1,4 @@ from pypy.rlib import rdynload -from pypy.jit.backend.x86.runner import CPU from pypy.rlib import rjitffi from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import OperationError, wrap_oserror @@ -65,14 +64,14 @@ class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - self.lib = space.wrap(W_Lib(self.space, name)) - self.name = name - self.cpu = CPU(None, None) + rjitffi.CDLL.__init__(self, name) + # XXX we load a library twice (in super-class and below) + self.lib_w = W_Lib(self.space, name) def get_w(self, func, w_args_type, res_type='void'): args_type_w = [ self.space.str_w(w_x) for w_x in self.space.listview(w_args_type) ] - return self.space.wrap(W_Get(self.space, self.cpu, self.space.wrap(self.lib), func, args_type_w, res_type)) + return self.space.wrap(W_Get(self.space, self.cpu, self.space.wrap(self.lib_w), func, args_type_w, res_type)) def descr_new_cdll(space, w_type, name): try: From getxsick at codespeak.net Tue Jun 22 03:59:08 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 03:59:08 +0200 (CEST) Subject: [pypy-svn] r75489 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100622015908.16349282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 03:59:07 2010 New Revision: 75489 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Log: put ObjSpace in unwrap_spec of W_CDLL.get_w() Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 03:59:07 2010 @@ -68,10 +68,15 @@ # XXX we load a library twice (in super-class and below) self.lib_w = W_Lib(self.space, name) - def get_w(self, func, w_args_type, res_type='void'): - args_type_w = [ self.space.str_w(w_x) - for w_x in self.space.listview(w_args_type) ] - return self.space.wrap(W_Get(self.space, self.cpu, self.space.wrap(self.lib_w), func, args_type_w, res_type)) + def get_w(self, space, func, w_args_type, res_type='void'): + args_type_w = [ space.str_w(w_x) + for w_x in space.listview(w_args_type) ] + return space.wrap(W_Get(space, + self.cpu, + space.wrap(self.lib_w), + func, + args_type_w, + res_type)) def descr_new_cdll(space, w_type, name): try: @@ -84,7 +89,7 @@ 'CDLL', __new__ = interp2app(descr_new_cdll), get = interp2app(W_CDLL.get_w, unwrap_spec=['self', - str, W_Root, str]), + ObjSpace, str, W_Root, str]), __doc__ = """ C Dynamically loaded library use CDLL(libname) to create a handle to a C library (the argument is processed the same way as dlopen processes it).""" From getxsick at codespeak.net Tue Jun 22 04:09:29 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 04:09:29 +0200 (CEST) Subject: [pypy-svn] r75490 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100622020929.1B6BD282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 04:09:27 2010 New Revision: 75490 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Log: tidy up typedef of classes Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 04:09:27 2010 @@ -14,16 +14,15 @@ self.space = space -def descr_new_lib(space, w_type, name): +def W_Lib___new__(space, w_type, name): try: return space.wrap(W_Lib(space, name)) except OSError, e: raise wrap_oserror(space, e) -descr_new_lib.unwrap_spec = [ObjSpace, W_Root, str] W_Lib.typedef = TypeDef( 'Lib', - __new__ = interp2app(descr_new_lib) + __new__ = interp2app(W_Lib___new__, unwrap_spec=[ObjSpace,W_Root,str]) ) class W_Get(Wrappable, rjitffi._Get): @@ -47,17 +46,15 @@ return space.wrap(self.call(args_w)) - -def descr_new_get(space, w_type, cpu, lib, func, args_type, res_type): +def W_Get___new__(space, w_type, cpu, lib, func, args_type, res_type): try: return space.wrap(W_Get(space, w_type, cpu, lib, func, args_type, res_type)) except OSError, e: raise wrap_oserror(space, e) -descr_new_get.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root, str, W_Root, str] W_Get.typedef = TypeDef( 'Get', - #__new__ = interp2app(descr_new_get) + #__new__ = interp2app(W_Get___new__, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, str, W_Root, str]), call = interp2app(W_Get.call_w, unwrap_spec=['self', ObjSpace, W_Root]) ) @@ -78,16 +75,15 @@ args_type_w, res_type)) -def descr_new_cdll(space, w_type, name): +def W_CDLL___new__(space, w_type, name): try: return space.wrap(W_CDLL(space, name)) except OSError, e: raise wrap_oserror(space, e) -descr_new_cdll.unwrap_spec = [ObjSpace, W_Root, str] W_CDLL.typedef = TypeDef( 'CDLL', - __new__ = interp2app(descr_new_cdll), + __new__ = interp2app(W_CDLL___new__,unwrap_spec=[ObjSpace,W_Root,str]), get = interp2app(W_CDLL.get_w, unwrap_spec=['self', ObjSpace, str, W_Root, str]), __doc__ = """ C Dynamically loaded library From getxsick at codespeak.net Tue Jun 22 04:16:58 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 04:16:58 +0200 (CEST) Subject: [pypy-svn] r75491 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100622021658.5BDEA282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 04:16:56 2010 New Revision: 75491 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Log: rename W_Lib to W_LibHandler just to avoid conflicts between W_Lib and W_CDLL names Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 04:16:56 2010 @@ -5,7 +5,7 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef -class W_Lib(Wrappable): +class W_LibHandler(Wrappable): def __init__(self, space, name): try: self.handler = rdynload.dlopen(name) @@ -14,17 +14,19 @@ self.space = space -def W_Lib___new__(space, w_type, name): +def W_LibHandler___new__(space, w_type, name): try: return space.wrap(W_Lib(space, name)) except OSError, e: raise wrap_oserror(space, e) -W_Lib.typedef = TypeDef( - 'Lib', - __new__ = interp2app(W_Lib___new__, unwrap_spec=[ObjSpace,W_Root,str]) +W_LibHandler.typedef = TypeDef( + 'LibHandler', + __new__ = interp2app(W_LibHandler___new__, unwrap_spec=[ObjSpace, + W_Root, str]) ) + class W_Get(Wrappable, rjitffi._Get): def __init__(self, space, cpu, lib, func, args_type, res_type='void'): self.space = space @@ -58,12 +60,12 @@ call = interp2app(W_Get.call_w, unwrap_spec=['self', ObjSpace, W_Root]) ) + class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - rjitffi.CDLL.__init__(self, name) - # XXX we load a library twice (in super-class and below) - self.lib_w = W_Lib(self.space, name) + rjitffi.CDLL.__init__(self, name, load=False) + self.lib_w = W_LibHandler(self.space, name) def get_w(self, space, func, w_args_type, res_type='void'): args_type_w = [ space.str_w(w_x) From getxsick at codespeak.net Tue Jun 22 04:26:19 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 04:26:19 +0200 (CEST) Subject: [pypy-svn] r75492 - pypy/branch/fast-ctypes/pypy/module/jitffi Message-ID: <20100622022619.120DB282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 04:26:17 2010 New Revision: 75492 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Log: revert excessive changes in r75491 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 04:26:17 2010 @@ -64,7 +64,8 @@ class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - rjitffi.CDLL.__init__(self, name, load=False) + rjitffi.CDLL.__init__(self, name) + # XXX we load a library twice (in super-class and below) self.lib_w = W_LibHandler(self.space, name) def get_w(self, space, func, w_args_type, res_type='void'): From antocuni at codespeak.net Tue Jun 22 15:14:27 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Jun 2010 15:14:27 +0200 (CEST) Subject: [pypy-svn] r75493 - in pypy/branch/sys-prefix/pypy: module/sys module/sys/test translator/goal translator/goal/test2 Message-ID: <20100622131427.77317282B90@codespeak.net> Author: antocuni Date: Tue Jun 22 15:14:25 2010 New Revision: 75493 Added: pypy/branch/sys-prefix/pypy/module/sys/test/test_initialpath.py (contents, props changed) Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py pypy/branch/sys-prefix/pypy/translator/goal/app_main.py pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py Log: improve the logic to search the library path: now lib_pypy and lib-python can be found either on one of the parent directories of pypy-c, or in lib/pypy1.2/. This allows multiple schemes of installation, such as: - /usr/bin/pypy-c, /usr/lib/pypy1.2/ - /opt/pypy/pypy-c, /opt/pypy/{lib_pypy, lib_python} - /opt/pypy/bin/pypy-c, /opt/pypy/{lib_pypy, lib_python} Moreover it has not been tested on windows, but it should allow to install pypy like this: - c:\pypy\pypy-c.exe, c:\pypy\{lib_pypy, lib-python} Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/state.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/state.py Tue Jun 22 15:14:25 2010 @@ -32,24 +32,30 @@ if not stat.S_ISDIR(st[0]): raise OSError(errno.ENOTDIR, path) -def getinitialpath(srcdir): - # build the initial path from the srcdir, which is the path of - # the "dist" directory of a PyPy checkout. - from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION - libdir = os.path.join(srcdir, 'lib') +def getinitialpath(prefix): + from pypy.module.sys.version import PYPY_VERSION + libdir = os.path.join(prefix, 'lib') pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) + # search for the stdlib both in $PREFIX/lib/pypy1.2 and $PREFIX + for lib_prefix in (pypyxy_dir, prefix): + try: + return get_importlist(lib_prefix) + except OSError: + pass + raise OSError # stdlib not foud +def get_importlist(lib_prefix): + from pypy.module.sys.version import CPYTHON_VERSION dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], CPYTHON_VERSION[1], CPYTHON_VERSION[2]) - lib_python = os.path.join(pypyxy_dir, 'lib-python') - + lib_python = os.path.join(lib_prefix, 'lib-python') python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) checkdir(python_std_lib_modified) - lib_pypy = os.path.join(pypyxy_dir, 'lib_pypy') + lib_pypy = os.path.join(lib_prefix, 'lib_pypy') checkdir(lib_pypy) importlist = [] Added: pypy/branch/sys-prefix/pypy/module/sys/test/test_initialpath.py ============================================================================== --- (empty file) +++ pypy/branch/sys-prefix/pypy/module/sys/test/test_initialpath.py Tue Jun 22 15:14:25 2010 @@ -0,0 +1,32 @@ +import py +from pypy.module.sys.state import getinitialpath +from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION + +def build_hierarchy(prefix): + dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], + CPYTHON_VERSION[1], + CPYTHON_VERSION[2]) + a = prefix.join('lib_pypy').ensure(dir=1) + b = prefix.join('lib-python', 'modified-%s' % dirname).ensure(dir=1) + c = prefix.join('lib-python', dirname).ensure(dir=1) + return a, b, c + + +def test_stdlib_in_pypyxy(tmpdir): + pypyxy = tmpdir.join('lib', 'pypy%d.%d' % PYPY_VERSION[:2]) + dirs = build_hierarchy(pypyxy) + path = getinitialpath(str(tmpdir)) + assert path == map(str, dirs) + + +def test_stdlib_in_prefix(tmpdir): + dirs = build_hierarchy(tmpdir) + path = getinitialpath(str(tmpdir)) + assert path == map(str, dirs) + +def test_stdlib_precedence(tmpdir): + pypyxy = tmpdir.join('lib', 'pypy%d.%d' % PYPY_VERSION[:2]) + dirs1 = build_hierarchy(tmpdir) + dirs2 = build_hierarchy(pypyxy) + path = getinitialpath(str(tmpdir)) + assert path == map(str, dirs2) Modified: pypy/branch/sys-prefix/pypy/translator/goal/app_main.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/app_main.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/app_main.py Tue Jun 22 15:14:25 2010 @@ -183,9 +183,6 @@ return argv[i], i def get_library_path(executable): - AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d' - # set up a sys.path that depends on the local machine - autosubpath = AUTOSUBPATH % sys.pypy_version_info[:2] search = executable while 1: dirname = resolvedirof(search) @@ -197,10 +194,8 @@ break newpath = sys.pypy_initial_path(dirname) if newpath is None: - newpath = sys.pypy_initial_path(os.path.join(dirname, autosubpath)) - if newpath is None: - search = dirname # walk to the parent directory - continue + search = dirname # walk to the parent directory + continue break # found! return newpath Modified: pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/test2/test_app_main.py Tue Jun 22 15:14:25 2010 @@ -486,6 +486,7 @@ self.w_goal_dir = self.space.wrap(goal_dir) self.w_fake_exe = self.space.wrap(str(fake_exe)) self.w_expected_path = self.space.wrap(expected_path) + self.w_trunkdir = self.space.wrap(os.path.dirname(autopath.pypydir)) def test_get_library_path(self): import sys @@ -500,3 +501,18 @@ assert newpath == self.expected_path finally: sys.path.pop() + + def test_trunk_can_be_prefix(self): + import sys + import os + sys.path.append(self.goal_dir) + try: + import app_main + app_main.os = os + pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c') + newpath = app_main.get_library_path(pypy_c) + assert len(newpath) == 3 + for p in newpath: + assert p.startswith(self.trunkdir) + finally: + sys.path.pop() From benjamin at codespeak.net Tue Jun 22 15:44:25 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 15:44:25 +0200 (CEST) Subject: [pypy-svn] r75494 - pypy/branch/fast-forward/pypy/objspace/std Message-ID: <20100622134425.4C30C282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 15:44:23 2010 New Revision: 75494 Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py Log: fix syntax Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 22 15:44:23 2010 @@ -734,7 +734,7 @@ if tp == "%": tp = "f" value *= 100 - if self._precision = -1: + if self._precision == -1: self._precision = 6 def format_float(self, w_float): From antocuni at codespeak.net Tue Jun 22 16:04:13 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Jun 2010 16:04:13 +0200 (CEST) Subject: [pypy-svn] r75495 - in pypy/branch/sys-prefix: lib lib-python lib_pypy lib_pypy/ctypes_config_cache pypy/annotation/test pypy/bin pypy/config pypy/doc/config pypy/jit/backend pypy/jit/backend/x86 pypy/jit/backend/x86/tool pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/module/__builtin__/test pypy/module/_codecs/test pypy/module/_sre/test pypy/module/sys/test pypy/rlib/parsing/test pypy/rlib/rsdl/test pypy/rpython/microbench pypy/tool pypy/tool/algo/test pypy/tool/pytest pypy/tool/test pypy/translator pypy/translator/benchmark pypy/translator/c pypy/translator/c/gcc pypy/translator/c/test pypy/translator/cli/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/microbench/pybench pypy/translator/sandbox pypy/translator/sandbox/test pypy/translator/test pypy/translator/tool site-packages Message-ID: <20100622140413.BA2F3282B90@codespeak.net> Author: antocuni Date: Tue Jun 22 16:04:11 2010 New Revision: 75495 Added: pypy/branch/sys-prefix/lib-python/ - copied from r75481, pypy/branch/sys-prefix/lib/pypy1.2/lib-python/ pypy/branch/sys-prefix/lib_pypy/ - copied from r75481, pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/ pypy/branch/sys-prefix/lib_pypy/py (contents, props changed) pypy/branch/sys-prefix/site-packages/ - copied from r75481, pypy/branch/sys-prefix/lib/pypy1.2/site-packages/ Removed: pypy/branch/sys-prefix/lib/ Modified: pypy/branch/sys-prefix/lib-python/conftest.py pypy/branch/sys-prefix/lib_pypy/ctypes_config_cache/rebuild.py pypy/branch/sys-prefix/pypy/annotation/test/autopath.py pypy/branch/sys-prefix/pypy/bin/autopath.py pypy/branch/sys-prefix/pypy/config/autopath.py pypy/branch/sys-prefix/pypy/doc/config/autopath.py pypy/branch/sys-prefix/pypy/jit/backend/autopath.py pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py pypy/branch/sys-prefix/pypy/jit/tl/autopath.py pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py pypy/branch/sys-prefix/pypy/jit/tool/autopath.py pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py pypy/branch/sys-prefix/pypy/tool/autopath.py pypy/branch/sys-prefix/pypy/tool/lib_pypy.py pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py pypy/branch/sys-prefix/pypy/tool/test/autopath.py pypy/branch/sys-prefix/pypy/translator/autopath.py pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py pypy/branch/sys-prefix/pypy/translator/c/autopath.py pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py pypy/branch/sys-prefix/pypy/translator/goal/autopath.py pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py pypy/branch/sys-prefix/pypy/translator/test/autopath.py pypy/branch/sys-prefix/pypy/translator/tool/autopath.py Log: move lib/pypy1.2/* to trunk/ Among the other things, this brings back lib-python to its original location Modified: pypy/branch/sys-prefix/lib-python/conftest.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib-python/conftest.py (original) +++ pypy/branch/sys-prefix/lib-python/conftest.py Tue Jun 22 16:04:11 2010 @@ -20,7 +20,7 @@ regrtestdir, modregrtestdir, testresultdir pytest_plugins = "resultlog", -rsyncdirs = ['.', '../../../pypy/'] +rsyncdirs = ['.', '../pypy/'] # # Interfacing/Integrating with py.test's collection process Modified: pypy/branch/sys-prefix/lib_pypy/ctypes_config_cache/rebuild.py ============================================================================== --- pypy/branch/sys-prefix/lib/pypy1.2/lib_pypy/ctypes_config_cache/rebuild.py (original) +++ pypy/branch/sys-prefix/lib_pypy/ctypes_config_cache/rebuild.py Tue Jun 22 16:04:11 2010 @@ -6,7 +6,7 @@ # get the correct path import os.path this_dir = os.path.dirname(__file__) -autopath_py = os.path.join(this_dir, '../../../../pypy/tool/autopath.py') +autopath_py = os.path.join(this_dir, '../../pypy/tool/autopath.py') autopath_py = os.path.abspath(autopath_py) execfile(autopath_py, dict(__name__='autopath', __file__=autopath_py)) Added: pypy/branch/sys-prefix/lib_pypy/py ============================================================================== --- (empty file) +++ pypy/branch/sys-prefix/lib_pypy/py Tue Jun 22 16:04:11 2010 @@ -0,0 +1 @@ +link ../py \ No newline at end of file Modified: pypy/branch/sys-prefix/pypy/annotation/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/annotation/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/annotation/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/bin/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/bin/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/bin/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/config/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/config/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/config/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/doc/config/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/config/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/doc/config/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/backend/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/x86/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/backend/x86/tool/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tl/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tl/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tl/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tl/spli/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/jit/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/jit/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/jit/tool/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/__builtin__/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/_codecs/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/_sre/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rlib/parsing/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rlib/rsdl/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/rpython/microbench/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/algo/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/lib_pypy.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/lib_pypy.py (original) +++ pypy/branch/sys-prefix/pypy/tool/lib_pypy.py Tue Jun 22 16:04:11 2010 @@ -1,19 +1,14 @@ import py import pypy import pypy.module -from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION +from pypy.module.sys.version import CPYTHON_VERSION -prefix = py.path.local(pypy.__path__[0]).dirpath() -pypy_ver = 'pypy%d.%d' % PYPY_VERSION[:2] - -LIB_ROOT = prefix.join('lib', pypy_ver) +LIB_ROOT = py.path.local(pypy.__path__[0]).dirpath() LIB_PYPY = LIB_ROOT.join('lib_pypy') LIB_PYTHON = LIB_ROOT.join('lib-python') LIB_PYTHON_VANILLA = LIB_PYTHON.join('%d.%d.%d' % CPYTHON_VERSION[:3]) LIB_PYTHON_MODIFIED = LIB_PYTHON.join('modified-%d.%d.%d' % CPYTHON_VERSION[:3]) -del prefix -del pypy_ver def import_from_lib_pypy(modname): modname = LIB_PYPY.join(modname+'.py') Modified: pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/pytest/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/tool/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/tool/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/benchmark/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/gcc/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/c/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/cli/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/goal/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/goal/test2/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/microbench/pybench/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/test/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/test/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/test/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/tool/autopath.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/tool/autopath.py (original) +++ pypy/branch/sys-prefix/pypy/translator/tool/autopath.py Tue Jun 22 16:04:11 2010 @@ -127,7 +127,7 @@ pypydir, this_dir = __dirinfo('pypy') import py # note: py is imported only AFTER the path has been set -libpythondir = str(py.path.local(pypydir).dirpath().join('lib', 'pypy1.2', 'lib-python', '2.5.2')) +libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) if __name__ == '__main__': From benjamin at codespeak.net Tue Jun 22 16:11:25 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 16:11:25 +0200 (CEST) Subject: [pypy-svn] r75496 - pypy/branch/fast-forward/pypy/module/sys Message-ID: <20100622141125.047A6282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 16:11:24 2010 New Revision: 75496 Modified: pypy/branch/fast-forward/pypy/module/sys/app.py Log: pypy/lib is in sys.path Modified: pypy/branch/fast-forward/pypy/module/sys/app.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/app.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/app.py Tue Jun 22 16:11:24 2010 @@ -3,7 +3,7 @@ The 'sys' module. """ -from pypy.lib._structseq import structseqtype, structseqfield +from _structseq import structseqtype, structseqfield def excepthook(exctype, value, traceback): """Handle an exception by displaying it with a traceback on sys.stderr.""" From benjamin at codespeak.net Tue Jun 22 16:43:36 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 16:43:36 +0200 (CEST) Subject: [pypy-svn] r75497 - pypy/branch/fast-forward/pypy/interpreter/astcompiler Message-ID: <20100622144336.D7CB1282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 16:43:35 2010 New Revision: 75497 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Log: use 2.7 future flags Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Tue Jun 22 16:43:35 2010 @@ -617,7 +617,7 @@ self.error("* not valid in __future__ imports", imp) for alias in imp.names: assert isinstance(alias, ast.alias) - if alias.name not in future.futureFlags_2_5.compiler_features: + if alias.name not in future.futureFlags_2_7.compiler_features: if alias.name == "braces": self.error("not a chance", imp) self.error("future feature %s is not defined" % From antocuni at codespeak.net Tue Jun 22 17:16:16 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Jun 2010 17:16:16 +0200 (CEST) Subject: [pypy-svn] r75498 - pypy/branch/sys-prefix/pypy/module/sys Message-ID: <20100622151616.56AB4282B90@codespeak.net> Author: antocuni Date: Tue Jun 22 17:16:13 2010 New Revision: 75498 Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py Log: iteration on tuples is not rpython Modified: pypy/branch/sys-prefix/pypy/module/sys/state.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/sys/state.py (original) +++ pypy/branch/sys-prefix/pypy/module/sys/state.py Tue Jun 22 17:16:13 2010 @@ -37,7 +37,7 @@ libdir = os.path.join(prefix, 'lib') pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) # search for the stdlib both in $PREFIX/lib/pypy1.2 and $PREFIX - for lib_prefix in (pypyxy_dir, prefix): + for lib_prefix in [pypyxy_dir, prefix]: try: return get_importlist(lib_prefix) except OSError: From antocuni at codespeak.net Tue Jun 22 17:23:06 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Jun 2010 17:23:06 +0200 (CEST) Subject: [pypy-svn] r75499 - pypy/branch/sys-prefix/pypy Message-ID: <20100622152306.E2DF3282B90@codespeak.net> Author: antocuni Date: Tue Jun 22 17:23:05 2010 New Revision: 75499 Modified: pypy/branch/sys-prefix/pypy/test_all.py Log: tweak the hack for the new directory structure Modified: pypy/branch/sys-prefix/pypy/test_all.py ============================================================================== --- pypy/branch/sys-prefix/pypy/test_all.py (original) +++ pypy/branch/sys-prefix/pypy/test_all.py Tue Jun 22 17:23:05 2010 @@ -4,30 +4,17 @@ """ This is a (hopefully temporary) hack. - Currently buildbot assumes that lib-python is under trunk/ and invokes - lib-python tests like this: + Currently buildbot assumes runs lib-python tests like this: python pypy/test_all.py --pypy=pypy/translator/goal/pypy-c \ --resultlog=cpython.log lib-python - However, now lib-python is under lib/pypy1.2/lib-python. We cannot just - change buildbot, as it would break all the other current branches, so - instead we replace lib-python with the correct path here. - - Note: instead of passing lib/pypy1.2/lib-python, but pass lib/pyyp1.2/ as - an argument: this way, the tests under lib_pypy are also run. + However, with the currenct buildbot configuration the tests under lib_pypy + are never run, so we monkey-patch the command line arguments to add it. """ import sys - from pypy.tool.lib_pypy import LIB_ROOT - if sys.argv and sys.argv[-1].endswith('lib-python'): - libpython = py.path.local(sys.argv[-1]) - if libpython.check(dir=True): - # the argument passed to the command line actually exists, so no - # need to patch it - return - else: - # patch it with the correct path - sys.argv[-1] = str(LIB_ROOT) + if sys.argv and sys.argv[-1] == 'lib-python': + sys.argv.append('lib_pypy') if __name__ == '__main__': From benjamin at codespeak.net Tue Jun 22 17:57:46 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 17:57:46 +0200 (CEST) Subject: [pypy-svn] r75500 - in pypy/branch/fast-forward/pypy: interpreter/astcompiler interpreter/pyparser interpreter/test module/__builtin__ module/__builtin__/test Message-ID: <20100622155746.0B190282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 17:57:45 2010 New Revision: 75500 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py pypy/branch/fast-forward/pypy/module/__builtin__/app_io.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Log: add print() function and print_function __future__ Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py Tue Jun 22 17:57:45 2010 @@ -15,6 +15,7 @@ CO_FUTURE_DIVISION = 0x2000 CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 CO_FUTURE_WITH_STATEMENT = 0x8000 +CO_FUTURE_PRINT_FUNCTION = 0x10000 PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pygram.py Tue Jun 22 17:57:45 2010 @@ -19,6 +19,9 @@ python_grammar = _get_python_grammar() +python_grammar_no_print = python_grammar.shared_copy() +python_grammar_no_print.keyword_ids = python_grammar_no_print.keyword_ids.copy() +del python_grammar_no_print.keyword_ids["print"] class _Tokens(object): pass Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/pyparse.py Tue Jun 22 17:57:45 2010 @@ -129,7 +129,10 @@ flags = compile_info.flags - self.grammar = pygram.python_grammar + if flags & consts.CO_FUTURE_PRINT_FUNCTION: + self.grammar = pygram.python_grammar_no_print + else: + self.grammar = pygram.python_grammar # The tokenizer is very picky about how it wants its input. source_lines = textsrc.splitlines(True) Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Tue Jun 22 17:57:45 2010 @@ -315,6 +315,27 @@ assert record == [2, 1] +class AppTestPrintFunction: + + def test_simple_print(self): + import __builtin__ + s = """from __future__ import print_function +x = print +""" + ns = {} + exec s in ns + assert ns["x"] is getattr(__builtin__, "print") + + def test_print(self): + s = """from __future__ import print_function +import StringIO +s = StringIO.StringIO() +print("Hello,", "person", file=s) +""" + ns = {} + exec s in ns + assert ns["s"].getvalue() == "Hello, person\n" + class AppTestWith: def test_with_simple(self): Modified: pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/__init__.py Tue Jun 22 17:57:45 2010 @@ -27,6 +27,7 @@ 'execfile' : 'app_io.execfile', 'raw_input' : 'app_io.raw_input', 'input' : 'app_io.input', + 'print' : 'app_io.print_', 'apply' : 'app_functional.apply', #'range' : 'app_functional.range', Modified: pypy/branch/fast-forward/pypy/module/__builtin__/app_io.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/app_io.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/app_io.py Tue Jun 22 17:57:45 2010 @@ -69,3 +69,48 @@ def input(prompt=None): """Equivalent to eval(raw_input(prompt)).""" return eval(raw_input(prompt)) + +def print_(*args, **kwargs): + """The new-style print function from py3k.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + def write(data): + if not isinstance(data, basestring): + data = str(data) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = u"\n" + space = u" " + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Tue Jun 22 17:57:45 2010 @@ -495,6 +495,44 @@ firstlineno = co.co_firstlineno assert firstlineno == 2 + def test_print_function(self): + import __builtin__ + import sys + import StringIO + pr = getattr(__builtin__, "print") + save = sys.stdout + out = sys.stdout = StringIO.StringIO() + try: + pr("Hello,", "person!") + finally: + sys.stdout = save + assert out.getvalue() == "Hello, person!\n" + out = StringIO.StringIO() + pr("Hello,", "person!", file=out) + assert out.getvalue() == "Hello, person!\n" + out = StringIO.StringIO() + pr("Hello,", "person!", file=out, end="") + assert out.getvalue() == "Hello, person!" + out = StringIO.StringIO() + pr("Hello,", "person!", file=out, sep="X") + assert out.getvalue() == "Hello,Xperson!\n" + out = StringIO.StringIO() + pr(u"Hello,", u"person!", file=out) + result = out.getvalue() + assert isinstance(result, unicode) + assert result == u"Hello, person!\n" + pr("Hello", file=None) # This works. + out = StringIO.StringIO() + pr(None, file=out) + assert out.getvalue == "None" + + def test_print_exceptions(self): + import __builtin__ + pr = getattr(__builtin__, "print") + raises(TypeError, pr, x=3) + raises(TypeError, pr, end=3) + raises(TypeError, pr, sep=42) + class AppTestBuiltinOptimized(object): def setup_class(cls): from pypy.conftest import gettestobjspace From benjamin at codespeak.net Tue Jun 22 18:06:43 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 18:06:43 +0200 (CEST) Subject: [pypy-svn] r75501 - pypy/branch/fast-forward/pypy/interpreter/astcompiler Message-ID: <20100622160643.E75ED282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 18:06:42 2010 New Revision: 75501 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Log: don't hardcode python version Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Tue Jun 22 18:06:42 2010 @@ -11,7 +11,6 @@ from pypy.interpreter.astcompiler import optimize # For side effects from pypy.interpreter.pyparser.error import SyntaxError from pypy.tool import stdlib_opcode as ops -from pypy.interpreter.pyparser import future from pypy.interpreter.error import OperationError from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX @@ -615,9 +614,10 @@ "of file", imp) if star_import: self.error("* not valid in __future__ imports", imp) + compiler = space.createcompiler() for alias in imp.names: assert isinstance(alias, ast.alias) - if alias.name not in future.futureFlags_2_7.compiler_features: + if alias.name not in compiler.future_flags.compiler_features: if alias.name == "braces": self.error("not a chance", imp) self.error("future feature %s is not defined" % From getxsick at codespeak.net Tue Jun 22 18:10:44 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 18:10:44 +0200 (CEST) Subject: [pypy-svn] r75502 - in pypy/branch/fast-ctypes/pypy: module/jitffi rlib Message-ID: <20100622161044.B1FA4282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 18:10:43 2010 New Revision: 75502 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: workaround to avoid double loading of library Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 18:10:43 2010 @@ -64,8 +64,7 @@ class W_CDLL(Wrappable, rjitffi.CDLL): def __init__(self, space, name): self.space = space - rjitffi.CDLL.__init__(self, name) - # XXX we load a library twice (in super-class and below) + rjitffi.CDLL.__init__(self, name, load=False) self.lib_w = W_LibHandler(self.space, name) def get_w(self, space, func, w_args_type, res_type='void'): Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 18:10:43 2010 @@ -7,11 +7,14 @@ from pypy.jit.metainterp.typesystem import deref class CDLL(object): - def __init__(self, name): - try: - self.lib = rdynload.dlopen(name) - except rdynload.DLOpenError, e: - raise OSError('%s: %s', name, e.msg or 'unspecified error') + def __init__(self, name, load=True): + if load: + try: + self.lib = rdynload.dlopen(name) + except rdynload.DLOpenError, e: + raise OSError('%s: %s', name, e.msg or 'unspecified error') + else: + self.lib = None self.name = name self.cpu = CPU(None, None) From benjamin at codespeak.net Tue Jun 22 18:19:27 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 18:19:27 +0200 (CEST) Subject: [pypy-svn] r75503 - pypy/branch/fast-forward/pypy/module/_codecs Message-ID: <20100622161927.11926282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 18:19:26 2010 New Revision: 75503 Modified: pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py Log: accept new utf-7 argument Modified: pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/fast-forward/pypy/module/_codecs/app_codecs.py Tue Jun 22 18:19:26 2010 @@ -53,7 +53,7 @@ res = u''.join(res) return res, len(data) -def utf_7_decode( data, errors='strict'): +def utf_7_decode( data, errors='strict', final=False): """None """ res = PyUnicode_DecodeUTF7(data, len(data), errors) From getxsick at codespeak.net Tue Jun 22 18:47:34 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 18:47:34 +0200 (CEST) Subject: [pypy-svn] r75504 - in pypy/branch/fast-ctypes/pypy/module/jitffi: . test Message-ID: <20100622164734.D2519282BDE@codespeak.net> Author: getxsick Date: Tue Jun 22 18:47:33 2010 New Revision: 75504 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: push the exception to app-level. more tests pass. Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 18:47:33 2010 @@ -70,12 +70,12 @@ def get_w(self, space, func, w_args_type, res_type='void'): args_type_w = [ space.str_w(w_x) for w_x in space.listview(w_args_type) ] - return space.wrap(W_Get(space, - self.cpu, - space.wrap(self.lib_w), - func, - args_type_w, - res_type)) + try: + ret = W_Get(space, self.cpu, space.wrap(self.lib_w), + func, args_type_w, res_type) + except ValueError, e: + raise OperationError(space.w_ValueError, space.wrap(str(e))) + return space.wrap(ret) def W_CDLL___new__(space, w_type, name): try: Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 18:47:33 2010 @@ -93,5 +93,5 @@ import jitffi lib = jitffi.CDLL(self.lib_name) # xxxfoo888baryyy - not existed function - py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', []) - py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') + raises(ValueError, lib.get, 'xxxfoo888baryyy', []) + raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') From benjamin at codespeak.net Tue Jun 22 18:52:53 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 18:52:53 +0200 (CEST) Subject: [pypy-svn] r75505 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler pyparser pyparser/test test Message-ID: <20100622165253.61AB0282B90@codespeak.net> Author: benjamin Date: Tue Jun 22 18:52:51 2010 New Revision: 75505 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: add from __future__ import unicode_literals support Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Tue Jun 22 18:52:51 2010 @@ -1,4 +1,4 @@ -from pypy.interpreter.astcompiler import ast, misc +from pypy.interpreter.astcompiler import ast, consts, misc from pypy.interpreter.astcompiler import asthelpers # Side effects from pypy.interpreter import error from pypy.interpreter.pyparser.pygram import syms, tokens @@ -1060,7 +1060,10 @@ elif first_child_type == tokens.STRING: space = self.space encoding = self.compile_info.encoding - sub_strings_w = [parsestring.parsestr(space, encoding, s.value) + flags = self.compile_info.flags + unicode_literals = flags & consts.CO_FUTURE_UNICODE_LITERALS + sub_strings_w = [parsestring.parsestr(space, encoding, s.value, + unicode_literals) for s in atom_node.children] # This implements implicit string concatenation. if len(sub_strings_w) > 1: Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/consts.py Tue Jun 22 18:52:51 2010 @@ -16,6 +16,7 @@ CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 CO_FUTURE_WITH_STATEMENT = 0x8000 CO_FUTURE_PRINT_FUNCTION = 0x10000 +CO_FUTURE_UNICODE_LITERALS = 0x20000 PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/parsestring.py Tue Jun 22 18:52:51 2010 @@ -1,7 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import unicodehelper -def parsestr(space, encoding, s): +def parsestr(space, encoding, s, unicode_literals=False): # compiler.transformer.Transformer.decode_literal depends on what # might seem like minor details of this function -- changes here # must be reflected there. @@ -11,7 +11,7 @@ ps = 0 quote = s[ps] rawmode = False - unicode = False + unicode = unicode_literals # string decoration handling o = ord(quote) @@ -20,6 +20,7 @@ if quote == 'b' or quote == 'B': ps += 1 quote = s[ps] + unicode = False elif quote == 'u' or quote == 'U': ps += 1 quote = s[ps] Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/test/test_parsestring.py Tue Jun 22 18:52:51 2010 @@ -69,6 +69,15 @@ ret = space.unwrap(w_ret) assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") + def test_unicode_literals(self): + space = self.space + w_ret = parsestring.parsestr(space, None, repr("hello"), True) + assert space.isinstance_w(w_ret, space.w_unicode) + w_ret = parsestring.parsestr(space, None, "b'hi'", True) + assert space.isinstance_w(w_ret, space.w_str) + w_ret = parsestring.parsestr(space, None, "r'hi'", True) + assert space.isinstance_w(w_ret, space.w_unicode) + def test_bytes(self): space = self.space b = "b'hello'" Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Tue Jun 22 18:52:51 2010 @@ -336,6 +336,25 @@ exec s in ns assert ns["s"].getvalue() == "Hello, person\n" + +class AppTestUnicodeLiterals: + + def test_simple(self): + s = """from __future__ import unicode_literals +x = 'u' +y = r'u' +z = u'u' +b = b'u' +c = br'u'""" + ns = {} + exec s in ns + assert isinstance(ns["x"], unicode) + assert isinstance(ns["y"], unicode) + assert isinstance(ns["z"], unicode) + assert isinstance(ns["b"], str) + assert isinstance(ns["c"], str) + + class AppTestWith: def test_with_simple(self): From getxsick at codespeak.net Tue Jun 22 18:54:53 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 18:54:53 +0200 (CEST) Subject: [pypy-svn] r75506 - in pypy/branch/fast-ctypes/pypy/module/jitffi: . test Message-ID: <20100622165453.816E5282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 18:54:52 2010 New Revision: 75506 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: another exception pushed to app-level. more more tests pass Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Tue Jun 22 18:54:52 2010 @@ -65,7 +65,10 @@ def __init__(self, space, name): self.space = space rjitffi.CDLL.__init__(self, name, load=False) - self.lib_w = W_LibHandler(self.space, name) + try: + self.lib_w = W_LibHandler(self.space, name) + except OSError, e: + raise OperationError(space.w_OSError, space.wrap(str(e))) def get_w(self, space, func, w_args_type, res_type='void'): args_type_w = [ space.str_w(w_x) Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 18:54:52 2010 @@ -57,8 +57,9 @@ cls.space = space cls.w_lib_name = space.wrap(cls.preprare_c_example()) - #def test_missing_lib(self): - # py.test.raises(OSError, rjitffi.CDLL, 'xxxfoo888baryyy') + def test_missing_lib(self): + import jitffi + raises(OSError, jitffi.CDLL, 'xxxfoo888baryyy') def test_get(self): import jitffi From getxsick at codespeak.net Tue Jun 22 19:19:14 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 19:19:14 +0200 (CEST) Subject: [pypy-svn] r75507 - pypy/branch/fast-ctypes/pypy/module/jitffi/test Message-ID: <20100622171914.E8386282B90@codespeak.net> Author: getxsick Date: Tue Jun 22 19:19:13 2010 New Revision: 75507 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Log: add more tests Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/test/test_jitffi.py Tue Jun 22 19:19:13 2010 @@ -96,3 +96,12 @@ # xxxfoo888baryyy - not existed function raises(ValueError, lib.get, 'xxxfoo888baryyy', []) raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') + + def test_unknown_types(self): + import jitffi + lib = jitffi.CDLL(self.lib_name) + # xxxfoo888baryyy - not defined types (args_type, res_type etc.) + raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy']) + raises(ValueError, lib.get, 'fvoid', ['int','xxxfoo888baryyy']) + raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy'],'int') + raises(ValueError, lib.get, 'fvoid', [], 'xxxfoo888baryyy') From getxsick at codespeak.net Tue Jun 22 19:59:56 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 19:59:56 +0200 (CEST) Subject: [pypy-svn] r75508 - in pypy/branch/fast-ctypes/pypy/rlib: . test Message-ID: <20100622175956.65D16282BDB@codespeak.net> Author: getxsick Date: Tue Jun 22 19:59:54 2010 New Revision: 75508 Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py Log: providing W_LibHandler class broke rlib.rjitffi a bit (and i just noticed it) so here is a dirty fix for it, also tests updated and new added Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 19:59:54 2010 @@ -28,7 +28,11 @@ self.args_type = args_type self.res_type = res_type self.cpu = cpu - self.lib = lib.handler + + if hasattr(lib, 'handler'): + self.lib = lib.handler + else: + self.lib = lib if self.res_type == 'int': self.bres = BoxInt() Modified: pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/test/test_rjitffi.py Tue Jun 22 19:59:54 2010 @@ -63,17 +63,17 @@ lib = rjitffi.CDLL(self.lib_name) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 3 == func.call(1,2) + assert 3 == func.call([1,2]) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 1 == func.call(-1,2) + assert 1 == func.call([-1,2]) func = lib.get('add_integers', ['int', 'int'], 'int') - assert 0 == func.call(0,0) + assert 0 == func.call([0,0]) func = lib.get('max3', ['int', 'int', 'int'], 'int') - assert 8 == func.call(2, 8, 3) + assert 8 == func.call([2, 8, 3]) func = lib.get('add_floats', ['float', 'float'], 'float') - assert 2.7 == func.call(1.2, 1.5) + assert 2.7 == func.call([1.2, 1.5]) def test_get_void(self): lib = rjitffi.CDLL(self.lib_name) @@ -82,12 +82,20 @@ assert 1 == func.call() func = lib.get('return_void', ['int', 'int'], 'void') - assert func.call(1, 2) is None + assert func.call([1, 2]) is None func = lib.get('return_void', ['int', 'int']) - assert func.call(1, 2) is None + assert func.call([1, 2]) is None def test_undefined_func(self): lib = rjitffi.CDLL(self.lib_name) # xxxfoo888baryyy - not existed function py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', []) py.test.raises(ValueError, lib.get, 'xxxfoo888baryyy', ['int'], 'int') + + def test_unknown_types(self): + lib = rjitffi.CDLL(self.lib_name) + # xxxfoo888baryyy - not defined types (args_type, res_type etc.) + py.test.raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy']) + py.test.raises(ValueError, lib.get, 'fvoid', ['int','xxxfoo888baryyy']) + py.test.raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy'],'int') + py.test.raises(ValueError, lib.get, 'fvoid', [], 'xxxfoo888baryyy') From getxsick at codespeak.net Tue Jun 22 20:03:47 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Tue, 22 Jun 2010 20:03:47 +0200 (CEST) Subject: [pypy-svn] r75509 - pypy/branch/fast-ctypes/pypy/rlib Message-ID: <20100622180347.BE6DC282BDB@codespeak.net> Author: getxsick Date: Tue Jun 22 20:03:45 2010 New Revision: 75509 Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: add a comment about the hack in r75508. just to keep in mind that should be refactored later Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Tue Jun 22 20:03:45 2010 @@ -29,7 +29,7 @@ self.res_type = res_type self.cpu = cpu - if hasattr(lib, 'handler'): + if hasattr(lib, 'handler'): # XXX dirty hack for pypy.module.jitffi self.lib = lib.handler else: self.lib = lib From benjamin at codespeak.net Tue Jun 22 22:10:05 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 22:10:05 +0200 (CEST) Subject: [pypy-svn] r75510 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler astcompiler/test astcompiler/tools pyparser/data test Message-ID: <20100622201005.9E837282BE0@codespeak.net> Author: benjamin Date: Tue Jun 22 22:10:02 2010 New Revision: 75510 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: implement class decorators Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py Tue Jun 22 22:10:02 2010 @@ -211,18 +211,18 @@ class FunctionDef(stmt): - __slots__ = ('name', 'args', 'body', 'w_body', 'decorators', 'w_decorators') + __slots__ = ('name', 'args', 'body', 'w_body', 'decorator_list', 'w_decorator_list') _lineno_mask = 16 _col_offset_mask = 32 - def __init__(self, name, args, body, decorators, lineno, col_offset): + def __init__(self, name, args, body, decorator_list, lineno, col_offset): self.name = name self.args = args self.body = body self.w_body = None - self.decorators = decorators - self.w_decorators = None + self.decorator_list = decorator_list + self.w_decorator_list = None stmt.__init__(self, lineno, col_offset) self.initialization_state = 63 @@ -232,13 +232,13 @@ def mutate_over(self, visitor): if self.body: visitor._mutate_sequence(self.body) - if self.decorators: - visitor._mutate_sequence(self.decorators) + if self.decorator_list: + visitor._mutate_sequence(self.decorator_list) return visitor.visit_FunctionDef(self) def sync_app_attrs(self, space): if (self.initialization_state & ~0) ^ 63: - missing_field(space, self.initialization_state, ['name', 'args', 'body', 'decorators', 'lineno', 'col_offset'], 'FunctionDef') + missing_field(space, self.initialization_state, ['name', 'args', 'body', 'decorator_list', 'lineno', 'col_offset'], 'FunctionDef') else: pass self.args.sync_app_attrs(space) @@ -252,33 +252,35 @@ if self.body is not None: for node in self.body: node.sync_app_attrs(space) - w_list = self.w_decorators + w_list = self.w_decorator_list if w_list is not None: list_w = space.listview(w_list) if list_w: - self.decorators = [space.interp_w(expr, w_obj) for w_obj in list_w] + self.decorator_list = [space.interp_w(expr, w_obj) for w_obj in list_w] else: - self.decorators = None - if self.decorators is not None: - for node in self.decorators: + self.decorator_list = None + if self.decorator_list is not None: + for node in self.decorator_list: node.sync_app_attrs(space) class ClassDef(stmt): - __slots__ = ('name', 'bases', 'w_bases', 'body', 'w_body') + __slots__ = ('name', 'bases', 'w_bases', 'body', 'w_body', 'decorator_list', 'w_decorator_list') - _lineno_mask = 8 - _col_offset_mask = 16 + _lineno_mask = 16 + _col_offset_mask = 32 - def __init__(self, name, bases, body, lineno, col_offset): + def __init__(self, name, bases, body, decorator_list, lineno, col_offset): self.name = name self.bases = bases self.w_bases = None self.body = body self.w_body = None + self.decorator_list = decorator_list + self.w_decorator_list = None stmt.__init__(self, lineno, col_offset) - self.initialization_state = 31 + self.initialization_state = 63 def walkabout(self, visitor): visitor.visit_ClassDef(self) @@ -288,11 +290,13 @@ visitor._mutate_sequence(self.bases) if self.body: visitor._mutate_sequence(self.body) + if self.decorator_list: + visitor._mutate_sequence(self.decorator_list) return visitor.visit_ClassDef(self) def sync_app_attrs(self, space): - if (self.initialization_state & ~0) ^ 31: - missing_field(space, self.initialization_state, ['name', 'bases', 'body', 'lineno', 'col_offset'], 'ClassDef') + if (self.initialization_state & ~0) ^ 63: + missing_field(space, self.initialization_state, ['name', 'bases', 'body', 'decorator_list', 'lineno', 'col_offset'], 'ClassDef') else: pass w_list = self.w_bases @@ -315,6 +319,16 @@ if self.body is not None: for node in self.body: node.sync_app_attrs(space) + w_list = self.w_decorator_list + if w_list is not None: + list_w = space.listview(w_list) + if list_w: + self.decorator_list = [space.interp_w(expr, w_obj) for w_obj in list_w] + else: + self.decorator_list = None + if self.decorator_list is not None: + for node in self.decorator_list: + node.sync_app_attrs(space) class Return(stmt): @@ -2583,14 +2597,16 @@ node.args.walkabout(self) if node.body: self.visit_sequence(node.body) - if node.decorators: - self.visit_sequence(node.decorators) + if node.decorator_list: + self.visit_sequence(node.decorator_list) def visit_ClassDef(self, node): if node.bases: self.visit_sequence(node.bases) if node.body: self.visit_sequence(node.body) + if node.decorator_list: + self.visit_sequence(node.decorator_list) def visit_Return(self, node): if node.value: @@ -3067,28 +3083,28 @@ w_self.w_body = w_new_value w_self.initialization_state |= 4 -def FunctionDef_get_decorators(space, w_self): +def FunctionDef_get_decorator_list(space, w_self): if not w_self.initialization_state & 8: - w_err = space.wrap("attribute 'decorators' has not been set") + w_err = space.wrap("attribute 'decorator_list' has not been set") raise OperationError(space.w_AttributeError, w_err) - if w_self.w_decorators is None: - if w_self.decorators is None: + if w_self.w_decorator_list is None: + if w_self.decorator_list is None: w_list = space.newlist([]) else: - list_w = [space.wrap(node) for node in w_self.decorators] + list_w = [space.wrap(node) for node in w_self.decorator_list] w_list = space.newlist(list_w) - w_self.w_decorators = w_list - return w_self.w_decorators + w_self.w_decorator_list = w_list + return w_self.w_decorator_list -def FunctionDef_set_decorators(space, w_self, w_new_value): - w_self.w_decorators = w_new_value +def FunctionDef_set_decorator_list(space, w_self, w_new_value): + w_self.w_decorator_list = w_new_value w_self.initialization_state |= 8 -_FunctionDef_field_unroller = unrolling_iterable(['name', 'args', 'body', 'decorators', 'lineno', 'col_offset']) +_FunctionDef_field_unroller = unrolling_iterable(['name', 'args', 'body', 'decorator_list', 'lineno', 'col_offset']) def FunctionDef_init(space, w_self, args): w_self = space.descr_self_interp_w(FunctionDef, w_self) w_self.w_body = None - w_self.w_decorators = None + w_self.w_decorator_list = None args_w, kwargs_w = args.unpack() if args_w: if len(args_w) != 6: @@ -3104,11 +3120,11 @@ FunctionDef.typedef = typedef.TypeDef("FunctionDef", stmt.typedef, - _fields=_FieldsWrapper(['name', 'args', 'body', 'decorators']), + _fields=_FieldsWrapper(['name', 'args', 'body', 'decorator_list']), name=typedef.GetSetProperty(FunctionDef_get_name, FunctionDef_set_name, cls=FunctionDef), args=typedef.GetSetProperty(FunctionDef_get_args, FunctionDef_set_args, cls=FunctionDef), body=typedef.GetSetProperty(FunctionDef_get_body, FunctionDef_set_body, cls=FunctionDef), - decorators=typedef.GetSetProperty(FunctionDef_get_decorators, FunctionDef_set_decorators, cls=FunctionDef), + decorator_list=typedef.GetSetProperty(FunctionDef_get_decorator_list, FunctionDef_set_decorator_list, cls=FunctionDef), __new__=interp2app(get_AST_new(FunctionDef)), __init__=interp2app(FunctionDef_init), ) @@ -3158,15 +3174,33 @@ w_self.w_body = w_new_value w_self.initialization_state |= 4 -_ClassDef_field_unroller = unrolling_iterable(['name', 'bases', 'body', 'lineno', 'col_offset']) +def ClassDef_get_decorator_list(space, w_self): + if not w_self.initialization_state & 8: + w_err = space.wrap("attribute 'decorator_list' has not been set") + raise OperationError(space.w_AttributeError, w_err) + if w_self.w_decorator_list is None: + if w_self.decorator_list is None: + w_list = space.newlist([]) + else: + list_w = [space.wrap(node) for node in w_self.decorator_list] + w_list = space.newlist(list_w) + w_self.w_decorator_list = w_list + return w_self.w_decorator_list + +def ClassDef_set_decorator_list(space, w_self, w_new_value): + w_self.w_decorator_list = w_new_value + w_self.initialization_state |= 8 + +_ClassDef_field_unroller = unrolling_iterable(['name', 'bases', 'body', 'decorator_list', 'lineno', 'col_offset']) def ClassDef_init(space, w_self, args): w_self = space.descr_self_interp_w(ClassDef, w_self) w_self.w_bases = None w_self.w_body = None + w_self.w_decorator_list = None args_w, kwargs_w = args.unpack() if args_w: - if len(args_w) != 5: - w_err = space.wrap("ClassDef constructor takes 0 or 5 positional arguments") + if len(args_w) != 6: + w_err = space.wrap("ClassDef constructor takes 0 or 6 positional arguments") raise OperationError(space.w_TypeError, w_err) i = 0 for field in _ClassDef_field_unroller: @@ -3178,10 +3212,11 @@ ClassDef.typedef = typedef.TypeDef("ClassDef", stmt.typedef, - _fields=_FieldsWrapper(['name', 'bases', 'body']), + _fields=_FieldsWrapper(['name', 'bases', 'body', 'decorator_list']), name=typedef.GetSetProperty(ClassDef_get_name, ClassDef_set_name, cls=ClassDef), bases=typedef.GetSetProperty(ClassDef_get_bases, ClassDef_set_bases, cls=ClassDef), body=typedef.GetSetProperty(ClassDef_get_body, ClassDef_set_body, cls=ClassDef), + decorator_list=typedef.GetSetProperty(ClassDef_get_decorator_list, ClassDef_set_decorator_list, cls=ClassDef), __new__=interp2app(get_AST_new(ClassDef)), __init__=interp2app(ClassDef_init), ) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Tue Jun 22 22:10:02 2010 @@ -458,21 +458,21 @@ self.error("expected \"with [expr] as [var]\"", with_var_node) return self.handle_expr(with_var_node.children[1]) - def handle_classdef(self, classdef_node): + def handle_classdef(self, classdef_node, decorators=None): name_node = classdef_node.children[1] name = name_node.value self.check_forbidden_name(name, name_node) if len(classdef_node.children) == 4: body = self.handle_suite(classdef_node.children[3]) - return ast.ClassDef(name, None, body, classdef_node.lineno, - classdef_node.column) + return ast.ClassDef(name, None, body, decorators, + classdef_node.lineno, classdef_node.column) if classdef_node.children[3].type == tokens.RPAR: body = self.handle_suite(classdef_node.children[5]) - return ast.ClassDef(name, None, body, classdef_node.lineno, - classdef_node.column) + return ast.ClassDef(name, None, body, decorators, + classdef_node.lineno, classdef_node.column) bases = self.handle_class_bases(classdef_node.children[3]) body = self.handle_suite(classdef_node.children[6]) - return ast.ClassDef(name, bases, body, classdef_node.lineno, + return ast.ClassDef(name, bases, body, decorators, classdef_node.lineno, classdef_node.column) def handle_class_bases(self, bases_node): @@ -480,21 +480,28 @@ return [self.handle_expr(bases_node.children[0])] return self.get_expression_list(bases_node) - def handle_funcdef(self, funcdef_node): - if len(funcdef_node.children) == 6: - decorators = self.handle_decorators(funcdef_node.children[0]) - name_index = 2 - else: - decorators = None - name_index = 1 - name_node = funcdef_node.children[name_index] + def handle_funcdef(self, funcdef_node, decorators=None): + name_node = funcdef_node.children[1] name = name_node.value self.check_forbidden_name(name, name_node) - args = self.handle_arguments(funcdef_node.children[name_index + 1]) - body = self.handle_suite(funcdef_node.children[name_index + 3]) + args = self.handle_arguments(funcdef_node.children[2]) + body = self.handle_suite(funcdef_node.children[4]) return ast.FunctionDef(name, args, body, decorators, funcdef_node.lineno, funcdef_node.column) + def handle_decorated(self, decorated_node): + decorators = self.handle_decorators(decorated_node.children[0]) + definition = decorated_node.children[1] + if definition.type == syms.funcdef: + node = self.handle_funcdef(definition, decorators) + elif definition.type == syms.classdef: + node = self.handle_classdef(definition, decorators) + else: + raise AssertionError("unkown decorated") + node.lineno = decorated_node.lineno + node.col_offset = decorated_node.column + return node + def handle_decorators(self, decorators_node): return [self.handle_decorator(dec) for dec in decorators_node.children] @@ -648,6 +655,8 @@ return self.handle_funcdef(stmt) elif stmt_type == syms.classdef: return self.handle_classdef(stmt) + elif stmt_type == syms.decorated: + return self.handle_decorated(stmt) else: raise AssertionError("unhandled compound statement") else: Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Tue Jun 22 22:10:02 2010 @@ -255,8 +255,8 @@ def visit_FunctionDef(self, func): self.update_position(func.lineno, True) # Load decorators first, but apply them after the function is created. - if func.decorators: - self.visit_sequence(func.decorators) + if func.decorator_list: + self.visit_sequence(func.decorator_list) if func.args.defaults: self.visit_sequence(func.args.defaults) num_defaults = len(func.args.defaults) @@ -266,8 +266,8 @@ func.lineno) self._make_function(code, num_defaults) # Apply decorators. - if func.decorators: - for i in range(len(func.decorators)): + if func.decorator_list: + for i in range(len(func.decorator_list)): self.emit_op_arg(ops.CALL_FUNCTION, 1) self.name_op(func.name, ast.Store) @@ -283,6 +283,8 @@ def visit_ClassDef(self, cls): self.update_position(cls.lineno, True) + if cls.decorator_list: + self.visit_sequence(cls.decorator_list) self.load_const(self.space.wrap(cls.name)) if cls.bases: bases_count = len(cls.bases) @@ -294,6 +296,9 @@ self._make_function(code, 0) self.emit_op_arg(ops.CALL_FUNCTION, 0) self.emit_op(ops.BUILD_CLASS) + if cls.decorator_list: + for i in range(len(cls.decorator_list)): + self.emit_op_arg(ops.CALL_FUNCTION, 1) self.name_op(cls.name, ast.Store) def _op_for_augassign(self, op): Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Tue Jun 22 22:10:02 2010 @@ -355,8 +355,8 @@ # Function defaults and decorators happen in the outer scope. if func.args.defaults: self.visit_sequence(func.args.defaults) - if func.decorators: - self.visit_sequence(func.decorators) + if func.decorator_list: + self.visit_sequence(func.decorator_list) new_scope = FunctionScope(func.name, func.lineno, func.col_offset) self.push_scope(new_scope, func) func.args.walkabout(self) @@ -371,6 +371,8 @@ self.note_symbol(clsdef.name, SYM_ASSIGNED) if clsdef.bases: self.visit_sequence(clsdef.bases) + if clsdef.decorator_list: + self.visit_sequence(clsdef.decorator_list) self.push_scope(ClassScope(clsdef), clsdef) self.visit_sequence(clsdef.body) self.pop_scope() Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Tue Jun 22 22:10:02 2010 @@ -467,6 +467,7 @@ assert len(cls.body) == 1 assert isinstance(cls.body[0], ast.Pass) assert cls.bases is None + assert cls.decorator_list is None for input in ("class X(Y): pass", "class X(Y,): pass"): cls = self.get_first_stmt(input) assert len(cls.bases) == 1 @@ -474,6 +475,7 @@ assert isinstance(base, ast.Name) assert base.ctx == ast.Load assert base.id == "Y" + assert cls.decorator_list is None cls = self.get_first_stmt("class X(Y, Z): pass") assert len(cls.bases) == 2 for b in cls.bases: @@ -486,7 +488,7 @@ assert func.name == "f" assert len(func.body) == 1 assert isinstance(func.body[0], ast.Pass) - assert func.decorators is None + assert func.decorator_list is None args = func.args assert isinstance(args, ast.arguments) assert args.args is None @@ -568,50 +570,53 @@ exc = py.test.raises(SyntaxError, self.get_ast, input).value assert exc.msg == "non-default argument follows default argument" - def test_decorator(self): - func = self.get_first_stmt("@dec\ndef f(): pass") - assert isinstance(func, ast.FunctionDef) - assert len(func.decorators) == 1 - dec = func.decorators[0] - assert isinstance(dec, ast.Name) - assert dec.id == "dec" - assert dec.ctx == ast.Load - func = self.get_first_stmt("@mod.hi.dec\ndef f(): pass") - assert len(func.decorators) == 1 - dec = func.decorators[0] - assert isinstance(dec, ast.Attribute) - assert dec.ctx == ast.Load - assert dec.attr == "dec" - assert isinstance(dec.value, ast.Attribute) - assert dec.value.attr == "hi" - assert isinstance(dec.value.value, ast.Name) - assert dec.value.value.id == "mod" - func = self.get_first_stmt("@dec\n at dec2\ndef f(): pass") - assert len(func.decorators) == 2 - for dec in func.decorators: + def test_decorators(self): + to_examine = (("def f(): pass", ast.FunctionDef), + ("class x: pass", ast.ClassDef)) + for stmt, node in to_examine: + definition = self.get_first_stmt("@dec\n%s" % (stmt,)) + assert isinstance(definition, node) + assert len(definition.decorator_list) == 1 + dec = definition.decorator_list[0] assert isinstance(dec, ast.Name) + assert dec.id == "dec" + assert dec.ctx == ast.Load + definition = self.get_first_stmt("@mod.hi.dec\n%s" % (stmt,)) + assert len(definition.decorator_list) == 1 + dec = definition.decorator_list[0] + assert isinstance(dec, ast.Attribute) assert dec.ctx == ast.Load - assert func.decorators[0].id == "dec" - assert func.decorators[1].id == "dec2" - func = self.get_first_stmt("@dec()\ndef f(): pass") - assert len(func.decorators) == 1 - dec = func.decorators[0] - assert isinstance(dec, ast.Call) - assert isinstance(dec.func, ast.Name) - assert dec.func.id == "dec" - assert dec.args is None - assert dec.keywords is None - assert dec.starargs is None - assert dec.kwargs is None - func = self.get_first_stmt("@dec(a, b)\ndef f(): pass") - assert len(func.decorators) == 1 - dec = func.decorators[0] - assert isinstance(dec, ast.Call) - assert dec.func.id == "dec" - assert len(dec.args) == 2 - assert dec.keywords is None - assert dec.starargs is None - assert dec.kwargs is None + assert dec.attr == "dec" + assert isinstance(dec.value, ast.Attribute) + assert dec.value.attr == "hi" + assert isinstance(dec.value.value, ast.Name) + assert dec.value.value.id == "mod" + definition = self.get_first_stmt("@dec\n at dec2\n%s" % (stmt,)) + assert len(definition.decorator_list) == 2 + for dec in definition.decorator_list: + assert isinstance(dec, ast.Name) + assert dec.ctx == ast.Load + assert definition.decorator_list[0].id == "dec" + assert definition.decorator_list[1].id == "dec2" + definition = self.get_first_stmt("@dec()\n%s" % (stmt,)) + assert len(definition.decorator_list) == 1 + dec = definition.decorator_list[0] + assert isinstance(dec, ast.Call) + assert isinstance(dec.func, ast.Name) + assert dec.func.id == "dec" + assert dec.args is None + assert dec.keywords is None + assert dec.starargs is None + assert dec.kwargs is None + definition = self.get_first_stmt("@dec(a, b)\n%s" % (stmt,)) + assert len(definition.decorator_list) == 1 + dec = definition.decorator_list[0] + assert isinstance(dec, ast.Call) + assert dec.func.id == "dec" + assert len(dec.args) == 2 + assert dec.keywords is None + assert dec.starargs is None + assert dec.kwargs is None def test_augassign(self): aug_assigns = ( Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl Tue Jun 22 22:10:02 2010 @@ -10,8 +10,8 @@ | Suite(stmt* body) stmt = FunctionDef(identifier name, arguments args, - stmt* body, expr* decorators) - | ClassDef(identifier name, expr* bases, stmt* body) + stmt* body, expr* decorator_list) + | ClassDef(identifier name, expr* bases, stmt* body, expr* decorator_list) | Return(expr? value) | Delete(expr* targets) Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Tue Jun 22 22:10:02 2010 @@ -33,7 +33,8 @@ decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ -funcdef: [decorators] 'def' NAME parameters ':' suite +decorated: decorators (classdef | funcdef) +funcdef: 'def' NAME parameters ':' suite parameters: '(' [varargslist] ')' varargslist: ((fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | @@ -73,7 +74,7 @@ exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Tue Jun 22 22:10:02 2010 @@ -313,6 +313,18 @@ @dec2 def g(): pass""" in ns assert record == [2, 1] + del record[:] + exec """@dec1 + at dec2 +class x: pass""" in ns + assert record == [2, 1] + + def test_class_decorators(self): + s = """@func +class x: pass""" + ns = {"func" : lambda cls: 4} + exec s in ns + assert ns["x"] == 4 class AppTestPrintFunction: From benjamin at codespeak.net Tue Jun 22 22:23:59 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 22:23:59 +0200 (CEST) Subject: [pypy-svn] r75511 - in pypy/branch/fast-forward/pypy/objspace: . test Message-ID: <20100622202359.042AA36C227@codespeak.net> Author: benjamin Date: Tue Jun 22 22:23:58 2010 New Revision: 75511 Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py Log: check an iterator for next in iter() Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/descroperation.py Tue Jun 22 22:23:58 2010 @@ -250,7 +250,12 @@ "'%s' object is not iterable", typename) return space.newseqiter(w_obj) - return space.get_and_call_function(w_descr, w_obj) + w_iter = space.get_and_call_function(w_descr, w_obj) + w_next = space.lookup(w_iter, 'next') + if w_next is None: + raise OperationError(space.w_TypeError, + space.wrap("iter() returned non-iterator")) + return w_iter def next(space, w_obj): w_descr = space.lookup(w_obj, 'next') Modified: pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py Tue Jun 22 22:23:58 2010 @@ -457,6 +457,12 @@ else: assert False, "did not raise" + def test_invalid_iterator(self): + class x(object): + def __iter__(self): + return self + raises(TypeError, iter, x()) + class AppTestWithBuiltinShortcut(AppTest_Descroperation): OPTIONS = {'objspace.std.builtinshortcut': True} From benjamin at codespeak.net Tue Jun 22 22:49:21 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 22:49:21 +0200 (CEST) Subject: [pypy-svn] r75512 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler astcompiler/test pyparser/data Message-ID: <20100622204921.78D58282BE0@codespeak.net> Author: benjamin Date: Tue Jun 22 22:49:19 2010 New Revision: 75512 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Log: make 'as' a full keyword Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Tue Jun 22 22:49:19 2010 @@ -186,10 +186,6 @@ if import_name_type == syms.import_as_name: name = import_name.children[0].value if len(import_name.children) == 3: - # 'as' is not yet a keyword in Python 2.5, so the grammar - # just specifies a NAME token. We check it manually here. - if import_name.children[1].value != "as": - self.error("must use 'as' in import", import_name) as_name = import_name.children[2].value self.check_forbidden_name(as_name, import_name.children[2]) else: @@ -200,8 +196,6 @@ if len(import_name.children) == 1: import_name = import_name.children[0] continue - if import_name.children[1].value != "as": - self.error("must use 'as' in import", import_name) alias = self.alias_for_import_name(import_name.children[0]) asname_node = import_name.children[2] alias.asname = asname_node.value @@ -446,18 +440,12 @@ body = self.handle_suite(with_node.children[-1]) if len(with_node.children) == 5: target_node = with_node.children[2] - target = self.handle_with_var(target_node) + target = self.handle_expr(target_node.children[1]) self.set_context(target, ast.Store) else: target = None return ast.With(test, target, body, with_node.lineno, with_node.column) - def handle_with_var(self, with_var_node): - # The grammar doesn't require 'as', so check it manually. - if with_var_node.children[0].value != "as": - self.error("expected \"with [expr] as [var]\"", with_var_node) - return self.handle_expr(with_var_node.children[1]) - def handle_classdef(self, classdef_node, decorators=None): name_node = classdef_node.children[1] name = name_node.value Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Tue Jun 22 22:49:19 2010 @@ -177,7 +177,6 @@ assert a2.name == "y" assert a2.asname == "w" exc = py.test.raises(SyntaxError, self.get_ast, "import x a b").value - assert exc.msg == "must use 'as' in import" def test_from_import(self): im = self.get_first_stmt("from x import y") @@ -224,7 +223,6 @@ assert a2.asname is None input = "from x import y a b" exc = py.test.raises(SyntaxError, self.get_ast, input).value - assert exc.msg == "must use 'as' in import" input = "from x import a, b," exc = py.test.raises(SyntaxError, self.get_ast, input).value assert exc.msg == "trailing comma is only allowed with surronding " \ @@ -457,7 +455,6 @@ assert wi.optional_vars.elts[0].ctx == ast.Store input = "with x hi y: pass" exc = py.test.raises(SyntaxError, self.get_ast, input).value - assert exc.msg == "expected \"with [expr] as [var]\"" def test_class(self): for input in ("class X: pass", "class X(): pass"): Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Tue Jun 22 22:49:19 2010 @@ -65,8 +65,8 @@ import_name: 'import' dotted_as_names import_from: ('from' ('.'* dotted_name | '.'+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) -import_as_name: NAME [('as' | NAME) NAME] -dotted_as_name: dotted_name [('as' | NAME) NAME] +import_as_name: NAME ['as' NAME] +dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* @@ -84,7 +84,7 @@ ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' test [ with_var ] ':' suite -with_var: ('as' | NAME) expr +with_var: 'as' expr # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [('as' | ',') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT From jcreigh at codespeak.net Tue Jun 22 22:55:58 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 22 Jun 2010 22:55:58 +0200 (CEST) Subject: [pypy-svn] r75513 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100622205558.0EE3A282BE0@codespeak.net> Author: jcreigh Date: Tue Jun 22 22:55:57 2010 New Revision: 75513 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Log: add test to catch case where a float comparision falls right on the edge of a MachineCodeBlock change Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Tue Jun 22 22:55:57 2010 @@ -2,7 +2,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr, rclass from pypy.jit.metainterp.history import ResOperation, LoopToken from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - Box, BasicFailDescr) + Box, BoxFloat, BasicFailDescr) from pypy.jit.backend.detect_cpu import getcpuclass from pypy.jit.backend.x86.arch import WORD from pypy.jit.backend.llsupport import symbolic @@ -395,3 +395,59 @@ self.cpu.set_future_value_int(0, base_v.value) self.cpu.execute_token(looptoken) assert self.cpu.get_latest_value_int(0) == 1024 + + def test_overflow_guard_float_cmp(self): + # The float comparisons on x86 tend to use small relative jumps, + # which may run into trouble if they fall on the edge of a + # MachineCodeBlock change. + a = BoxFloat(1.0) + b = BoxFloat(2.0) + failed = BoxInt(41) + finished = BoxInt(42) + + # We select guards that will always succeed, so that execution will + # continue through the entire set of comparisions + ops_to_test = ( + (rop.FLOAT_LT, [a, b], rop.GUARD_TRUE), + (rop.FLOAT_LT, [b, a], rop.GUARD_FALSE), + + (rop.FLOAT_LE, [a, a], rop.GUARD_TRUE), + (rop.FLOAT_LE, [a, b], rop.GUARD_TRUE), + (rop.FLOAT_LE, [b, a], rop.GUARD_FALSE), + + (rop.FLOAT_EQ, [a, a], rop.GUARD_TRUE), + (rop.FLOAT_EQ, [a, b], rop.GUARD_FALSE), + + (rop.FLOAT_NE, [a, b], rop.GUARD_TRUE), + (rop.FLOAT_NE, [a, a], rop.GUARD_FALSE), + + (rop.FLOAT_GT, [b, a], rop.GUARD_TRUE), + (rop.FLOAT_GT, [a, b], rop.GUARD_FALSE), + + (rop.FLOAT_GE, [a, a], rop.GUARD_TRUE), + (rop.FLOAT_GE, [b, a], rop.GUARD_TRUE), + (rop.FLOAT_GE, [a, b], rop.GUARD_FALSE), + ) + + for float_op, args, guard_op in ops_to_test: + ops = [] + + for i in range(200): + cmp_result = BoxInt() + ops.append(ResOperation(float_op, args, cmp_result)) + ops.append(ResOperation(guard_op, [cmp_result], None, descr=BasicFailDescr())) + ops[-1].fail_args = [failed] + + ops.append(ResOperation(rop.FINISH, [finished], None, descr=BasicFailDescr())) + + looptoken = LoopToken() + self.cpu.compile_loop([a, b, failed, finished], ops, looptoken) + self.cpu.set_future_value_float(0, a.value) + self.cpu.set_future_value_float(1, b.value) + self.cpu.set_future_value_int(2, failed.value) + self.cpu.set_future_value_int(3, finished.value) + self.cpu.execute_token(looptoken) + + # Really just a sanity check. We're actually interested in + # whether the test segfaults. + assert self.cpu.get_latest_value_int(0) == finished.value From jcreigh at codespeak.net Tue Jun 22 22:57:27 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 22 Jun 2010 22:57:27 +0200 (CEST) Subject: [pypy-svn] r75514 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100622205727.A4F0F282BE0@codespeak.net> Author: jcreigh Date: Tue Jun 22 22:57:26 2010 New Revision: 75514 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: fix float comparision bug (see test added in r75513) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Tue Jun 22 22:57:26 2010 @@ -647,7 +647,8 @@ mc = self.mc._mc mc.J_il8(rx86.Conditions['P'], 2) mc.J_il8(rx86.Conditions[cond], 5) - return self.implement_guard(addr) + mc.JMP_l(addr) + return mc.tell() - 4 return self.implement_guard(addr, false_cond) return genop_cmp_guard_float @@ -844,7 +845,8 @@ else: mc.J_il8(rx86.Conditions['P'], 2) mc.J_il8(rx86.Conditions['E'], 5) - return self.implement_guard(addr) + mc.JMP_l(addr) + return mc.tell() - 4 def genop_float_neg(self, op, arglocs, resloc): # Following what gcc does: res = x ^ 0x8000000000000000 From benjamin at codespeak.net Tue Jun 22 23:33:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 22 Jun 2010 23:33:09 +0200 (CEST) Subject: [pypy-svn] r75515 - in pypy/branch/fast-forward: lib-python/modified-2.7.0 pypy/tool Message-ID: <20100622213309.E6BCF282BE0@codespeak.net> Author: benjamin Date: Tue Jun 22 23:33:08 2010 New Revision: 75515 Added: pypy/branch/fast-forward/lib-python/modified-2.7.0/opcode.py (contents, props changed) Modified: pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py Log: switch to 2.7 opcode set Added: pypy/branch/fast-forward/lib-python/modified-2.7.0/opcode.py ============================================================================== --- (empty file) +++ pypy/branch/fast-forward/lib-python/modified-2.7.0/opcode.py Tue Jun 22 23:33:08 2010 @@ -0,0 +1,197 @@ + +""" +opcode module - potentially shared between dis and other modules which +operate on bytecodes (e.g. peephole optimizers). +""" + +__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs", + "haslocal", "hascompare", "hasfree", "opname", "opmap", + "HAVE_ARGUMENT", "EXTENDED_ARG"] + +cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', + 'is not', 'exception match', 'BAD') + +hasconst = [] +hasname = [] +hasjrel = [] +hasjabs = [] +haslocal = [] +hascompare = [] +hasfree = [] + +opmap = {} +opname = [''] * 256 +for op in range(256): opname[op] = '<%r>' % (op,) +del op + +def def_op(name, op): + opname[op] = name + opmap[name] = op + +def name_op(name, op): + def_op(name, op) + hasname.append(op) + +def jrel_op(name, op): + def_op(name, op) + hasjrel.append(op) + +def jabs_op(name, op): + def_op(name, op) + hasjabs.append(op) + +# Instruction opcodes for compiled code +# Blank lines correspond to available opcodes + +def_op('STOP_CODE', 0) +def_op('POP_TOP', 1) +def_op('ROT_TWO', 2) +def_op('ROT_THREE', 3) +def_op('DUP_TOP', 4) +def_op('ROT_FOUR', 5) + +def_op('NOP', 9) +def_op('UNARY_POSITIVE', 10) +def_op('UNARY_NEGATIVE', 11) +def_op('UNARY_NOT', 12) +def_op('UNARY_CONVERT', 13) + +def_op('UNARY_INVERT', 15) + +def_op('BINARY_POWER', 19) +def_op('BINARY_MULTIPLY', 20) +def_op('BINARY_DIVIDE', 21) +def_op('BINARY_MODULO', 22) +def_op('BINARY_ADD', 23) +def_op('BINARY_SUBTRACT', 24) +def_op('BINARY_SUBSCR', 25) +def_op('BINARY_FLOOR_DIVIDE', 26) +def_op('BINARY_TRUE_DIVIDE', 27) +def_op('INPLACE_FLOOR_DIVIDE', 28) +def_op('INPLACE_TRUE_DIVIDE', 29) +def_op('SLICE+0', 30) +def_op('SLICE+1', 31) +def_op('SLICE+2', 32) +def_op('SLICE+3', 33) + +def_op('STORE_SLICE+0', 40) +def_op('STORE_SLICE+1', 41) +def_op('STORE_SLICE+2', 42) +def_op('STORE_SLICE+3', 43) + +def_op('DELETE_SLICE+0', 50) +def_op('DELETE_SLICE+1', 51) +def_op('DELETE_SLICE+2', 52) +def_op('DELETE_SLICE+3', 53) + +def_op('STORE_MAP', 54) +def_op('INPLACE_ADD', 55) +def_op('INPLACE_SUBTRACT', 56) +def_op('INPLACE_MULTIPLY', 57) +def_op('INPLACE_DIVIDE', 58) +def_op('INPLACE_MODULO', 59) +def_op('STORE_SUBSCR', 60) +def_op('DELETE_SUBSCR', 61) +def_op('BINARY_LSHIFT', 62) +def_op('BINARY_RSHIFT', 63) +def_op('BINARY_AND', 64) +def_op('BINARY_XOR', 65) +def_op('BINARY_OR', 66) +def_op('INPLACE_POWER', 67) +def_op('GET_ITER', 68) + +def_op('PRINT_EXPR', 70) +def_op('PRINT_ITEM', 71) +def_op('PRINT_NEWLINE', 72) +def_op('PRINT_ITEM_TO', 73) +def_op('PRINT_NEWLINE_TO', 74) +def_op('INPLACE_LSHIFT', 75) +def_op('INPLACE_RSHIFT', 76) +def_op('INPLACE_AND', 77) +def_op('INPLACE_XOR', 78) +def_op('INPLACE_OR', 79) +def_op('BREAK_LOOP', 80) +def_op('WITH_CLEANUP', 81) +def_op('LOAD_LOCALS', 82) +def_op('RETURN_VALUE', 83) +def_op('IMPORT_STAR', 84) +def_op('EXEC_STMT', 85) +def_op('YIELD_VALUE', 86) +def_op('POP_BLOCK', 87) +def_op('END_FINALLY', 88) +def_op('BUILD_CLASS', 89) + +HAVE_ARGUMENT = 90 # Opcodes from here have an argument: + +name_op('STORE_NAME', 90) # Index in name list +name_op('DELETE_NAME', 91) # "" +def_op('UNPACK_SEQUENCE', 92) # Number of tuple items +jrel_op('FOR_ITER', 93) +def_op('LIST_APPEND', 94) +name_op('STORE_ATTR', 95) # Index in name list +name_op('DELETE_ATTR', 96) # "" +name_op('STORE_GLOBAL', 97) # "" +name_op('DELETE_GLOBAL', 98) # "" +def_op('DUP_TOPX', 99) # number of items to duplicate +def_op('LOAD_CONST', 100) # Index in const list +hasconst.append(100) +name_op('LOAD_NAME', 101) # Index in name list +def_op('BUILD_TUPLE', 102) # Number of tuple items +def_op('BUILD_LIST', 103) # Number of list items +def_op('BUILD_SET', 104) # Number of set items +def_op('BUILD_MAP', 105) # Number of dict entries (upto 255) +name_op('LOAD_ATTR', 106) # Index in name list +def_op('COMPARE_OP', 107) # Comparison operator +hascompare.append(107) +name_op('IMPORT_NAME', 108) # Index in name list +name_op('IMPORT_FROM', 109) # Index in name list +jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip +jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code +jabs_op('JUMP_IF_TRUE_OR_POP', 112) # "" +jabs_op('JUMP_ABSOLUTE', 113) # "" +jabs_op('POP_JUMP_IF_FALSE', 114) # "" +jabs_op('POP_JUMP_IF_TRUE', 115) # "" + +name_op('LOAD_GLOBAL', 116) # Index in name list + +jabs_op('CONTINUE_LOOP', 119) # Target address +jrel_op('SETUP_LOOP', 120) # Distance to target address +jrel_op('SETUP_EXCEPT', 121) # "" +jrel_op('SETUP_FINALLY', 122) # "" + +def_op('LOAD_FAST', 124) # Local variable number +haslocal.append(124) +def_op('STORE_FAST', 125) # Local variable number +haslocal.append(125) +def_op('DELETE_FAST', 126) # Local variable number +haslocal.append(126) + +def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) +def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8) +def_op('MAKE_FUNCTION', 132) # Number of args with default values +def_op('BUILD_SLICE', 133) # Number of items +def_op('MAKE_CLOSURE', 134) +def_op('LOAD_CLOSURE', 135) +hasfree.append(135) +def_op('LOAD_DEREF', 136) +hasfree.append(136) +def_op('STORE_DEREF', 137) +hasfree.append(137) + +def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8) +def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8) +def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8) + +jrel_op('SETUP_WITH', 143) + +def_op('EXTENDED_ARG', 145) +EXTENDED_ARG = 145 +def_op('SET_ADD', 146) +def_op('MAP_ADD', 147) + +# pypy modification, experimental bytecode +def_op('CALL_LIKELY_BUILTIN', 200) # #args + (#kwargs << 8) +def_op('LOOKUP_METHOD', 201) # Index in name list +def_op('CALL_METHOD', 202) # #args not including 'self' + +del def_op, name_op, jrel_op, jabs_op Modified: pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py (original) +++ pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py Tue Jun 22 23:33:08 2010 @@ -4,6 +4,8 @@ (module attributes with the `host_` prefix). """ +from pypy.module.sys.version import CPYTHON_VERSION_DIR + # load opcode.py as pythonopcode from our own lib __all__ = ['opmap', 'opname', 'HAVE_ARGUMENT', @@ -107,7 +109,8 @@ def load_pypy_opcode(): import py - opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.5.2/opcode.py') + lib_python = 'lib-python/modified-%s/opcode.py' % (CPYTHON_VERSION_DIR,) + opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath(lib_python) d = {} execfile(str(opcode_path), d) for name in __all__: From benjamin at codespeak.net Wed Jun 23 05:11:38 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 05:11:38 +0200 (CEST) Subject: [pypy-svn] r75516 - in pypy/branch/fast-forward/pypy: interpreter interpreter/astcompiler interpreter/astcompiler/test objspace/flow objspace/std Message-ID: <20100623031138.D2517282BD6@codespeak.net> Author: benjamin Date: Wed Jun 23 05:11:36 2010 New Revision: 75516 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/optimize.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py pypy/branch/fast-forward/pypy/interpreter/pycode.py pypy/branch/fast-forward/pypy/interpreter/pyframe.py pypy/branch/fast-forward/pypy/interpreter/pyopcode.py pypy/branch/fast-forward/pypy/objspace/flow/flowcontext.py pypy/branch/fast-forward/pypy/objspace/std/frame.py Log: switch to 2.7 bytecode Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py Wed Jun 23 05:11:36 2010 @@ -303,18 +303,29 @@ return max_depth block.marked = True block.initial_depth = depth + done = False for instr in block.instructions: depth += _opcode_stack_effect(instr.opcode, instr.arg) if depth >= max_depth: max_depth = depth if instr.has_jump: + target_depth = depth + jump_op = instr.opcode + if jump_op == ops.FOR_ITER: + target_depth -= 2 + elif (jump_op == ops.SETUP_FINALLY or + jump_op == ops.SETUP_EXCEPT): + target_depth += 3 + if target_depth > max_depth: + max_depth = target_depth max_depth = self._recursive_stack_depth_walk(instr.jump[0], - depth, max_depth) - if instr.opcode == ops.JUMP_ABSOLUTE or \ - instr.opcode == ops.JUMP_FORWARD: + target_depth, + max_depth) + if jump_op == ops.JUMP_ABSOLUTE or jump_op == ops.JUMP_FORWARD: # Nothing more can occur. + done = True break - if block.next_block: + if block.next_block and not done: max_depth = self._recursive_stack_depth_walk(block.next_block, depth, max_depth) block.marked = False @@ -488,9 +499,9 @@ ops.WITH_CLEANUP : -1, ops.POP_BLOCK : 0, - ops.END_FINALLY : -1, - ops.SETUP_FINALLY : 3, - ops.SETUP_EXCEPT : 3, + ops.END_FINALLY : -3, + ops.SETUP_FINALLY : 0, + ops.SETUP_EXCEPT : 0, ops.LOAD_LOCALS : 1, ops.RETURN_VALUE : -1, @@ -525,13 +536,15 @@ ops.LOAD_CONST : 1, ops.IMPORT_STAR : -1, - ops.IMPORT_NAME : 0, + ops.IMPORT_NAME : -1, ops.IMPORT_FROM : 1, ops.JUMP_FORWARD : 0, ops.JUMP_ABSOLUTE : 0, - ops.JUMP_IF_TRUE : 0, - ops.JUMP_IF_FALSE : 0, + ops.JUMP_IF_TRUE_OR_POP : 0, + ops.JUMP_IF_FALSE_OR_POP : 0, + ops.POP_JUMP_IF_TRUE : -1, + ops.POP_JUMP_IF_FALSE : -1, } @@ -548,7 +561,7 @@ return 1 - arg def _compute_MAKE_CLOSURE(arg): - return -arg + return -arg - 1 def _compute_MAKE_FUNCTION(arg): return -arg Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Wed Jun 23 05:11:36 2010 @@ -340,7 +340,6 @@ self.update_position(asrt.lineno) end = self.new_block() asrt.test.accept_jump_if(self, True, end) - self.emit_op(ops.POP_TOP) self.emit_op_name(ops.LOAD_GLOBAL, self.names, "AssertionError") if asrt.msg: asrt.msg.walkabout(self) @@ -348,7 +347,6 @@ else: self.emit_op_arg(ops.RAISE_VARARGS, 1) self.use_next_block(end) - self.emit_op(ops.POP_TOP) def _binop(self, op): if op == ast.Div: @@ -409,14 +407,15 @@ elif test_constant == optimize.CONST_TRUE: self.visit_sequence(if_.body) else: - next = self.new_block() - if_.test.accept_jump_if(self, False, next) - self.emit_op(ops.POP_TOP) + if if_.orelse: + otherwise = self.new_block() + else: + otherwise = end + if_.test.accept_jump_if(self, False, otherwise) self.visit_sequence(if_.body) self.emit_jump(ops.JUMP_FORWARD, end) - self.use_next_block(next) - self.emit_op(ops.POP_TOP) if if_.orelse: + self.use_next_block(otherwise) self.visit_sequence(if_.orelse) self.use_next_block(end) @@ -495,12 +494,10 @@ # Force another lineno to be set for tracing purposes. self.lineno_set = False wh.test.accept_jump_if(self, False, anchor) - self.emit_op(ops.POP_TOP) self.visit_sequence(wh.body) self.emit_jump(ops.JUMP_ABSOLUTE, loop, True) if test_constant == optimize.CONST_NOT_CONST: self.use_next_block(anchor) - self.emit_op(ops.POP_TOP) self.emit_op(ops.POP_BLOCK) self.pop_frame_block(F_BLOCK_LOOP, loop) if wh.orelse: @@ -528,8 +525,7 @@ self.emit_op(ops.DUP_TOP) handler.type.walkabout(self) self.emit_op_arg(ops.COMPARE_OP, 10) - self.emit_jump(ops.JUMP_IF_FALSE, next_except) - self.emit_op(ops.POP_TOP) + self.emit_jump(ops.POP_JUMP_IF_FALSE, next_except, True) self.emit_op(ops.POP_TOP) if handler.name: handler.name.walkabout(self) @@ -539,8 +535,6 @@ self.visit_sequence(handler.body) self.emit_jump(ops.JUMP_FORWARD, end) self.use_next_block(next_except) - if handler.type: - self.emit_op(ops.POP_TOP) self.emit_op(ops.END_FINALLY) self.use_next_block(otherwise) if te.orelse: @@ -834,14 +828,13 @@ def visit_BoolOp(self, op): self.update_position(op.lineno) if op.op == ast.And: - instr = ops.JUMP_IF_FALSE + instr = ops.JUMP_IF_FALSE_OR_POP else: - instr = ops.JUMP_IF_TRUE + instr = ops.JUMP_IF_TRUE_OR_POP end = self.new_block() for value in op.values[:-1]: value.walkabout(self) - self.emit_jump(instr, end) - self.emit_op(ops.POP_TOP) + self.emit_jump(instr, end, True) op.values[-1].walkabout(self) self.use_next_block(end) @@ -858,8 +851,7 @@ self.emit_op(ops.ROT_THREE) op_kind = compare_operations(comp.ops[i - 1]) self.emit_op_arg(ops.COMPARE_OP, op_kind) - self.emit_jump(ops.JUMP_IF_FALSE, cleanup) - self.emit_op(ops.POP_TOP) + self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup) if i < (ops_count - 1): comp.comparators[i].walkabout(self) comp.comparators[-1].walkabout(self) @@ -878,11 +870,9 @@ end = self.new_block() otherwise = self.new_block() ifexp.test.accept_jump_if(self, False, otherwise) - self.emit_op(ops.POP_TOP) ifexp.body.walkabout(self) self.emit_jump(ops.JUMP_FORWARD, end) self.use_next_block(otherwise) - self.emit_op(ops.POP_TOP) ifexp.orelse.walkabout(self) self.use_next_block(end) @@ -1004,7 +994,7 @@ self.emit_op_arg(ops.CALL_METHOD, arg_count) return True - def _listcomp_generator(self, list_name, gens, gen_index, elt): + def _listcomp_generator(self, gens, gen_index, elt): start = self.new_block() skip = self.new_block() if_cleanup = self.new_block() @@ -1022,34 +1012,23 @@ for if_ in gen.ifs: if_.accept_jump_if(self, False, if_cleanup) self.use_next_block() - self.emit_op(ops.POP_TOP) else: if_count = 0 gen_index += 1 if gen_index < len(gens): - self._listcomp_generator(list_name, gens, gen_index, elt) + self._listcomp_generator(gens, gen_index, elt) else: - self.name_op(list_name, ast.Load) elt.walkabout(self) - self.emit_op(ops.LIST_APPEND) + self.emit_op_arg(ops.LIST_APPEND, gen_index) self.use_next_block(skip) - for i in range(if_count): - self.emit_op_arg(ops.JUMP_FORWARD, 1) - if i == 0: - self.use_next_block(if_cleanup) - self.emit_op(ops.POP_TOP) + self.use_next_block(if_cleanup) self.emit_jump(ops.JUMP_ABSOLUTE, start, True) self.use_next_block(anchor) - if gen_index == 1: - self.name_op(list_name, ast.Del) def visit_ListComp(self, lc): self.update_position(lc.lineno) - tmp_name = self.current_temporary_name() self.emit_op_arg(ops.BUILD_LIST, 0) - self.emit_op(ops.DUP_TOP) - self.name_op(tmp_name, ast.Store) - self._listcomp_generator(tmp_name, lc.generators, 0, lc.elt) + self._listcomp_generator(lc.generators, 0, lc.elt) def _genexp_generator(self, generators, gen_index, elt): start = self.new_block() @@ -1063,7 +1042,7 @@ self.push_frame_block(F_BLOCK_LOOP, start) if gen_index == 0: self.argcount = 1 - self.name_op(".0", ast.Load) + self.emit_op_arg(ops.LOAD_FAST, 0) else: gen.iter.walkabout(self) self.emit_op(ops.GET_ITER) @@ -1076,7 +1055,6 @@ for if_ in gen.ifs: if_.accept_jump_if(self, False, if_cleanup) self.use_next_block() - self.emit_op(ops.POP_TOP) else: ifs_count = 0 gen_index += 1 @@ -1087,11 +1065,7 @@ self.emit_op(ops.YIELD_VALUE) self.emit_op(ops.POP_TOP) self.use_next_block(skip) - for i in range(ifs_count): - self.emit_op_arg(ops.JUMP_FORWARD, 1) - if i == 0: - self.use_next_block(if_cleanup) - self.emit_op(ops.POP_TOP) + self.use_next_block(if_cleanup) self.emit_jump(ops.JUMP_ABSOLUTE, start, True) self.use_next_block(anchor) self.emit_op(ops.POP_BLOCK) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/optimize.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/optimize.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/optimize.py Wed Jun 23 05:11:36 2010 @@ -45,9 +45,9 @@ def accept_jump_if(self, gen, condition, target): self.walkabout(gen) if condition: - gen.emit_jump(ops.JUMP_IF_TRUE, target) + gen.emit_jump(ops.POP_JUMP_IF_TRUE, target, True) else: - gen.emit_jump(ops.JUMP_IF_FALSE, target) + gen.emit_jump(ops.POP_JUMP_IF_FALSE, target, True) class __extend__(ast.Num): @@ -83,7 +83,6 @@ def _accept_jump_if_any_is(self, gen, condition, target): self.values[0].accept_jump_if(gen, condition, target) for i in range(1, len(self.values)): - gen.emit_op(ops.POP_TOP) self.values[i].accept_jump_if(gen, condition, target) def accept_jump_if(self, gen, condition, target): Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Wed Jun 23 05:11:36 2010 @@ -436,7 +436,6 @@ outer.iter.walkabout(self) new_scope = FunctionScope("genexp", genexp.lineno, genexp.col_offset) self.push_scope(new_scope, genexp) - self.implicit_arg(0) outer.target.walkabout(self) if outer.ifs: self.visit_sequence(outer.ifs) @@ -444,10 +443,6 @@ genexp.elt.walkabout(self) self.pop_scope() - def visit_ListComp(self, lc): - self.scope.new_temporary_name() - ast.GenericASTVisitor.visit_ListComp(self, lc) - def visit_With(self, wih): self.scope.new_temporary_name() if wih.optional_vars: Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jun 23 05:11:36 2010 @@ -41,7 +41,7 @@ co_expr = compile(evalexpr, '', 'eval') space = self.space pyco_expr = PyCode._from_code(space, co_expr) - w_res = pyco_expr.exec_code(space, w_dict, w_dict) + w_res = pyco_expr.exec_host_bytecode(space, w_dict, w_dict) res = space.str_w(space.repr(w_res)) if not isinstance(expected, float): assert res == repr(expected) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Wed Jun 23 05:11:36 2010 @@ -321,14 +321,8 @@ assert exc.msg == "return outside function" def test_tmpnames(self): - scp = self.mod_scope("[x for x in y]") - assert scp.lookup("_[1]") == symtable.SCOPE_LOCAL scp = self.mod_scope("with x: pass") assert scp.lookup("_[1]") == symtable.SCOPE_LOCAL scp = self.mod_scope("with x as y: pass") assert scp.lookup("_[1]") == symtable.SCOPE_LOCAL assert scp.lookup("_[2]") == symtable.SCOPE_LOCAL - # Just in case. - scp = self.mod_scope("with [x for y in z]: pass") - assert scp.lookup("_[1]") == symtable.SCOPE_LOCAL - assert scp.lookup("_[2]") == symtable.SCOPE_LOCAL Modified: pypy/branch/fast-forward/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pycode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pycode.py Wed Jun 23 05:11:36 2010 @@ -254,6 +254,12 @@ tuple(self.co_freevars), tuple(self.co_cellvars) ) + def exec_host_bytecode(self, w_dict, w_globals, w_locals): + from pypy.interpreter.pyframe import CPythonFrame + frame = CPythonFrame(self.space, self, w_globals, None) + frame.setdictscope(w_locals) + return frame.run() + def dump(self): """A dis.dis() dump of the code object.""" co = self._to_code() Modified: pypy/branch/fast-forward/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyframe.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyframe.py Wed Jun 23 05:11:36 2010 @@ -12,6 +12,7 @@ from pypy.rlib.debug import make_sure_not_resized from pypy.rlib import jit, rstack from pypy.tool import stdlib_opcode +from pypy.tool.stdlib_opcode import host_bytecode_spec # Define some opcodes used g = globals() @@ -135,7 +136,8 @@ # the following 'assert' is an annotation hint: it hides from # the annotator all methods that are defined in PyFrame but # overridden in the {,Host}FrameClass subclasses of PyFrame. - assert isinstance(self, self.space.FrameClass) + assert (isinstance(self, self.space.FrameClass) or + not self.space.config.translating) executioncontext = self.space.getexecutioncontext() executioncontext.enter(self) try: @@ -629,6 +631,18 @@ return space.wrap(self.builtin is not space.builtin) return space.w_False +class CPythonFrame(PyFrame): + """ + Execution of host (CPython) opcodes. + """ + + bytecode_spec = host_bytecode_spec + opcode_method_names = host_bytecode_spec.method_names + opcodedesc = host_bytecode_spec.opcodedesc + opdescmap = host_bytecode_spec.opdescmap + HAVE_ARGUMENT = host_bytecode_spec.HAVE_ARGUMENT + + # ____________________________________________________________ def get_block_class(opname): Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Wed Jun 23 05:11:36 2010 @@ -768,11 +768,7 @@ modulename = self.space.str_w(w_modulename) w_fromlist = self.popvalue() - # CPython 2.5 adds an extra argument consumed by this opcode - if self.pycode.magic >= 0xa0df294: - w_flag = self.popvalue() - else: - w_flag = None + w_flag = self.popvalue() w_import = self.get_builtin().getdictvalue(space, '__import__') if w_import is None: @@ -830,6 +826,32 @@ next_instr += stepby return next_instr + def POP_JUMP_IF_FALSE(self, target, next_instr): + w_value = self.popvalue() + if not self.space.is_true(w_value): + return target + return next_instr + + def POP_JUMP_IF_TRUE(self, target, next_instr): + w_value = self.popvalue() + if self.space.is_true(w_value): + return target + return next_instr + + def JUMP_IF_FALSE_OR_POP(self, target, next_instr): + w_value = self.peekvalue() + if not self.space.is_true(w_value): + return target + self.popvalue() + return next_instr + + def JUMP_IF_TRUE_OR_POP(self, target, next_instr): + w_value = self.peekvalue() + if self.space.is_true(w_value): + return target + self.popvalue() + return next_instr + def GET_ITER(self, oparg, next_instr): w_iterable = self.popvalue() w_iterator = self.space.iter(w_iterable) @@ -968,7 +990,7 @@ def LIST_APPEND(self, oparg, next_instr): w = self.popvalue() - v = self.popvalue() + v = self.peekvalue(oparg) self.space.call_method(v, 'append', w) def SET_LINENO(self, lineno, next_instr): @@ -1014,14 +1036,49 @@ STOP_CODE = MISSING_OPCODE def BUILD_MAP(self, itemcount, next_instr): - if itemcount != 0: - raise BytecodeCorruption w_dict = self.space.newdict() self.pushvalue(w_dict) def STORE_MAP(self, zero, next_instr): raise BytecodeCorruption + +class __extends__(pyframe.CPythonFrame): + + def BUILD_MAP(self, itemcount, next_instr): + if sys.version_info >= (2, 6): + # We could pre-allocate a dict here + # but for the moment this code is not translated. + pass + else: + if itemcount != 0: + raise BytecodeCorruption + w_dict = self.space.newdict() + self.pushvalue(w_dict) + + def LIST_APPEND(self, oparg, next_instr): + w_value = self.popvalue() + w_list = self.peekvalue(oparg + 1) + self.space.call_method(w_list, "append", w_value) + + def STORE_MAP(self, zero, next_instr): + if sys.version_info >= (2, 6): + w_key = self.popvalue() + w_value = self.popvalue() + w_dict = self.peekvalue() + self.space.setitem(w_dict, w_key, w_value) + else: + raise BytecodeCorruption + + def LIST_APPEND(self, oparg, next_instr): + w = self.popvalue() + if sys.version_info < (2, 7): + v = self.popvalue() + else: + v = self.peekvalue(oparg - 1) + self.space.call_method(v, 'append', w) + + ### ____________________________________________________________ ### class ExitFrame(Exception): Modified: pypy/branch/fast-forward/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/flow/flowcontext.py (original) +++ pypy/branch/fast-forward/pypy/objspace/flow/flowcontext.py Wed Jun 23 05:11:36 2010 @@ -397,70 +397,7 @@ stack_items_w[i] = w_new break -class FlowSpaceFrame(pyframe.PyFrame): - """ - Execution of host (CPython) opcodes. - """ - bytecode_spec = host_bytecode_spec - opcode_method_names = host_bytecode_spec.method_names - opcodedesc = host_bytecode_spec.opcodedesc - opdescmap = host_bytecode_spec.opdescmap - HAVE_ARGUMENT = host_bytecode_spec.HAVE_ARGUMENT - - def BUILD_MAP(self, itemcount, next_instr): - if sys.version_info >= (2, 6): - # We could pre-allocate a dict here - # but for the moment this code is not translated. - pass - else: - if itemcount != 0: - raise BytecodeCorruption - w_dict = self.space.newdict() - self.pushvalue(w_dict) - - def STORE_MAP(self, zero, next_instr): - if sys.version_info >= (2, 6): - w_key = self.popvalue() - w_value = self.popvalue() - w_dict = self.peekvalue() - self.space.setitem(w_dict, w_key, w_value) - else: - raise BytecodeCorruption - - def POP_JUMP_IF_FALSE(self, jumpto, next_instr): - w_cond = self.popvalue() - if not self.space.is_true(w_cond): - next_instr = jumpto - return next_instr - - def POP_JUMP_IF_TRUE(self, jumpto, next_instr): - w_cond = self.popvalue() - if self.space.is_true(w_cond): - return jumpto - return next_instr - - def JUMP_IF_FALSE_OR_POP(self, jumpto, next_instr): - w_cond = self.peekvalue() - if not self.space.is_true(w_cond): - return jumpto - self.popvalue() - return next_instr - - def JUMP_IF_TRUE_OR_POP(self, jumpto, next_instr): - w_cond = self.peekvalue() - if self.space.is_true(w_cond): - return jumpto - self.popvalue() - return next_instr - - def LIST_APPEND(self, oparg, next_instr): - w = self.popvalue() - if sys.version_info < (2, 7): - v = self.popvalue() - else: - v = self.peekvalue(oparg - 1) - self.space.call_method(v, 'append', w) - +class FlowSpaceFrame(pyframe.CPythonFrame): # XXX Unimplemented 2.7 opcodes ---------------- # Set literals, set comprehensions @@ -478,9 +415,6 @@ # `with` statement - def SETUP_WITH(self, oparg, next_instr): - raise NotImplementedError("SETUP_WITH") - def make_arguments(self, nargs): return ArgumentsForTranslation(self.space, self.peekvalues(nargs)) Modified: pypy/branch/fast-forward/pypy/objspace/std/frame.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/frame.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/frame.py Wed Jun 23 05:11:36 2010 @@ -18,7 +18,7 @@ def LIST_APPEND(f, oparg, next_instr): w = f.popvalue() - v = f.popvalue() + v = f.peekvalue(oparg) if type(v) is W_ListObject: v.append(w) else: From benjamin at codespeak.net Wed Jun 23 05:14:32 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 05:14:32 +0200 (CEST) Subject: [pypy-svn] r75517 - pypy/branch/fast-forward/pypy/interpreter/test Message-ID: <20100623031432.B9602282BD6@codespeak.net> Author: benjamin Date: Wed Jun 23 05:14:31 2010 New Revision: 75517 Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_interpreter.py Log: hidden list comp variables are no more Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_interpreter.py Wed Jun 23 05:14:31 2010 @@ -212,13 +212,6 @@ ''' assert self.codetest(code, 'callme', [1, 2, 3]) == 6 - def test_list_comprehension(self): - code = ''' - def f(): - return [dir() for i in [1]][0] - ''' - assert self.codetest(code, 'f', [])[0] == '_[1]' - def test_import_statement(self): for x in range(10): import os From benjamin at codespeak.net Wed Jun 23 05:31:46 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 05:31:46 +0200 (CEST) Subject: [pypy-svn] r75518 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100623033146.047D536C22E@codespeak.net> Author: benjamin Date: Wed Jun 23 05:31:45 2010 New Revision: 75518 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Log: generators must recieve an implicit first argument Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Wed Jun 23 05:31:45 2010 @@ -436,6 +436,7 @@ outer.iter.walkabout(self) new_scope = FunctionScope("genexp", genexp.lineno, genexp.col_offset) self.push_scope(new_scope, genexp) + self.implicit_arg(0) outer.target.walkabout(self) if outer.ifs: self.visit_sequence(outer.ifs) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Wed Jun 23 05:31:45 2010 @@ -81,6 +81,7 @@ self.check_unknown(scp, "y", "x") self.check_unknown(gscp, "z") assert gscp.lookup("y") == symtable.SCOPE_LOCAL + assert gscp.lookup(".0") == symtable.SCOPE_LOCAL scp, gscp = self.gen_scope("(x for x in z if x)") self.check_unknown(scp, "x") assert gscp.lookup("x") == symtable.SCOPE_LOCAL From antocuni at codespeak.net Wed Jun 23 10:48:11 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jun 2010 10:48:11 +0200 (CEST) Subject: [pypy-svn] r75519 - pypy/branch/sys-prefix/pypy Message-ID: <20100623084811.AF94336C22E@codespeak.net> Author: antocuni Date: Wed Jun 23 10:48:08 2010 New Revision: 75519 Modified: pypy/branch/sys-prefix/pypy/test_all.py Log: remove the hack. It doesn't work as it confuses the lib-python tests, which are reported as failing even if they are not Modified: pypy/branch/sys-prefix/pypy/test_all.py ============================================================================== --- pypy/branch/sys-prefix/pypy/test_all.py (original) +++ pypy/branch/sys-prefix/pypy/test_all.py Wed Jun 23 10:48:08 2010 @@ -1,24 +1,6 @@ #! /usr/bin/env python -def fix_lib_python_path(): - """ - This is a (hopefully temporary) hack. - - Currently buildbot assumes runs lib-python tests like this: - - python pypy/test_all.py --pypy=pypy/translator/goal/pypy-c \ - --resultlog=cpython.log lib-python - - However, with the currenct buildbot configuration the tests under lib_pypy - are never run, so we monkey-patch the command line arguments to add it. - """ - import sys - if sys.argv and sys.argv[-1] == 'lib-python': - sys.argv.append('lib_pypy') - - if __name__ == '__main__': import tool.autopath import py - fix_lib_python_path() py.cmdline.pytest() From antocuni at codespeak.net Wed Jun 23 10:56:34 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jun 2010 10:56:34 +0200 (CEST) Subject: [pypy-svn] r75520 - in pypy/branch/sys-prefix/pypy/tool: . test Message-ID: <20100623085634.85529282BAD@codespeak.net> Author: antocuni Date: Wed Jun 23 10:56:32 2010 New Revision: 75520 Modified: pypy/branch/sys-prefix/pypy/tool/package.py pypy/branch/sys-prefix/pypy/tool/test/test_package.py Log: fix package.py for the new directory layout Modified: pypy/branch/sys-prefix/pypy/tool/package.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/package.py (original) +++ pypy/branch/sys-prefix/pypy/tool/package.py Wed Jun 23 10:56:32 2010 @@ -40,8 +40,11 @@ pypydir = builddir.ensure(name, dir=True) # Careful: to copy lib_pypy, copying just the svn-tracked files # would not be enough: there are also ctypes_config_cache/_*_cache.py. - shutil.copytree(str(basedir.join('lib')), - str(pypydir.join('lib')), + shutil.copytree(str(basedir.join('lib-python')), + str(pypydir.join('lib-python')), + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + shutil.copytree(str(basedir.join('lib_pypy')), + str(pypydir.join('lib_pypy')), ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) Modified: pypy/branch/sys-prefix/pypy/tool/test/test_package.py ============================================================================== --- pypy/branch/sys-prefix/pypy/tool/test/test_package.py (original) +++ pypy/branch/sys-prefix/pypy/tool/test/test_package.py Wed Jun 23 10:56:32 2010 @@ -2,7 +2,7 @@ import py from pypy.tool.autopath import pypydir from pypy.tool.package import main -from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION +from pypy.module.sys.version import CPYTHON_VERSION import tarfile, os def test_dir_structure(): @@ -16,17 +16,16 @@ try: builddir = main(py.path.local(pypydir).dirpath(), 'test') prefix = builddir.join('test') - pypyxy = 'pypy%d.%d' % PYPY_VERSION[:2] cpyver = '%d.%d.%d' % CPYTHON_VERSION[:3] - assert prefix.join('lib', pypyxy, 'lib-python', cpyver, 'test').check() + assert prefix.join('lib-python', cpyver, 'test').check() assert prefix.join('bin', 'pypy-c').check() - assert prefix.join('lib', pypyxy, 'lib_pypy', 'syslog.py').check() - assert not prefix.join('lib', pypyxy, 'lib_pypy', 'py').check() - assert not prefix.join('lib', pypyxy, 'lib_pypy', 'ctypes_configure').check() + assert prefix.join('lib_pypy', 'syslog.py').check() + assert not prefix.join('lib_pypy', 'py').check() + assert not prefix.join('lib_pypy', 'ctypes_configure').check() assert prefix.join('LICENSE').check() assert prefix.join('README').check() th = tarfile.open(str(builddir.join('test.tar.bz2'))) - assert th.getmember('test/lib/%s/lib_pypy/syslog.py' % pypyxy) + assert th.getmember('test/lib_pypy/syslog.py') finally: if fake_pypy_c: pypy_c.remove() From antocuni at codespeak.net Wed Jun 23 13:33:10 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jun 2010 13:33:10 +0200 (CEST) Subject: [pypy-svn] r75521 - in pypy/branch/sys-prefix/pypy/translator/sandbox: . test Message-ID: <20100623113310.DEBBB282BAD@codespeak.net> Author: antocuni Date: Wed Jun 23 13:33:07 2010 New Revision: 75521 Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py Log: fix sandbox for the new directory hierarchy Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/pypy_interact.py Wed Jun 23 13:33:07 2010 @@ -51,15 +51,18 @@ tmpdirnode = Dir({}) else: tmpdirnode = RealDir(self.tmpdir, exclude=exclude) - libpath = str(LIB_ROOT.dirpath()) + libroot = str(LIB_ROOT) return Dir({ 'bin': Dir({ 'pypy-c': RealFile(self.executable), - 'lib': RealDir(libpath, exclude=exclude), - }), - 'tmp': tmpdirnode, - }) + 'lib-python': RealDir(os.path.join(libroot, 'lib-python'), + exclude=exclude), + 'lib_pypy': RealDir(os.path.join(libroot, 'lib_pypy'), + exclude=exclude), + }), + 'tmp': tmpdirnode, + }) if __name__ == '__main__': Modified: pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py ============================================================================== --- pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py (original) +++ pypy/branch/sys-prefix/pypy/translator/sandbox/test/test_pypy_interact.py Wed Jun 23 13:33:07 2010 @@ -24,7 +24,7 @@ assert_(argv[0] == '/bin/pypy-c', "bad argv[0]") st = os.lstat('/bin/pypy-c') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for /bin/pypy-c") - for dirname in ['/bin/lib/pypy1.2/lib-python/2.5.2', '/bin/lib/pypy1.2/lib_pypy']: + for dirname in ['/bin/lib-python/2.5.2', '/bin/lib_pypy']: st = os.stat(dirname) assert_(stat.S_ISDIR(st.st_mode), "bad st_mode for " + dirname) assert_(os.environ.get('PYTHONPATH') is None, "unexpected $PYTHONPATH") @@ -34,15 +34,15 @@ pass else: assert_(False, "os.stat('site') should have failed") - st = os.stat('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.py') + st = os.stat('/bin/lib-python/modified-2.5.2/site.py') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for .../site.py") try: - os.stat('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.pyc') + os.stat('/bin/lib-python/modified-2.5.2/site.pyc') except OSError: pass else: assert_(False, "os.stat('....pyc') should have failed") - fd = os.open('/bin/lib/pypy1.2/lib-python/modified-2.5.2/site.py', os.O_RDONLY, 0666) + fd = os.open('/bin/lib-python/modified-2.5.2/site.py', os.O_RDONLY, 0666) length = 8192 ofs = 0 while True: @@ -70,7 +70,7 @@ def setup_module(mod): t = Translation(mini_pypy_like_entry_point, backend='c', - standalone=True, sandbox=True) + standalone=True, sandbox=True) mod.executable = str(t.compile()) From antocuni at codespeak.net Wed Jun 23 13:35:24 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jun 2010 13:35:24 +0200 (CEST) Subject: [pypy-svn] r75522 - pypy/branch/sys-prefix/pypy/doc Message-ID: <20100623113524.0DB6F36C22E@codespeak.net> Author: antocuni Date: Wed Jun 23 13:35:23 2010 New Revision: 75522 Modified: pypy/branch/sys-prefix/pypy/doc/_ref.txt pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt Log: fix links Modified: pypy/branch/sys-prefix/pypy/doc/_ref.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/_ref.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/_ref.txt Wed Jun 23 13:35:23 2010 @@ -1,7 +1,7 @@ .. _`demo/`: ../../demo .. _`demo/pickle_coroutine.py`: ../../demo/pickle_coroutine.py -.. _`lib-python/`: ../../lib/pypy1.2/lib-python -.. _`lib-python/2.5.2/dis.py`: ../../lib/pypy1.2/lib-python/2.5.2/dis.py +.. _`lib-python/`: ../../lib-python +.. _`lib-python/2.5.2/dis.py`: ../../lib-python/2.5.2/dis.py .. _`annotation/`: .. _`pypy/annotation`: ../../pypy/annotation .. _`pypy/annotation/annrpython.py`: ../../pypy/annotation/annrpython.py @@ -46,10 +46,10 @@ .. _`pypy/interpreter/astcompiler/ast.py`: ../../pypy/interpreter/astcompiler/ast.py .. _`pypy/interpreter/typedef.py`: ../../pypy/interpreter/typedef.py .. _`lib/`: -.. _`lib_pypy/`: ../../lib/pypy1.2/lib_pypy -.. _`lib/distributed/`: ../../lib/pypy1.2/lib_pypy/distributed -.. _`lib_pypy/stackless.py`: ../../lib/pypy1.2/lib_pypy/stackless.py -.. _`lib_pypy/pypy_test/`: ../../lib/pypy1.2/lib_pypy/pypy_test +.. _`lib_pypy/`: ../../lib_pypy +.. _`lib/distributed/`: ../../lib_pypy/distributed +.. _`lib_pypy/stackless.py`: ../../lib_pypy/stackless.py +.. _`lib_pypy/pypy_test/`: ../../lib_pypy/pypy_test .. _`module/`: .. _`pypy/module`: .. _`pypy/module/`: ../../pypy/module Modified: pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt ============================================================================== --- pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt (original) +++ pypy/branch/sys-prefix/pypy/doc/objspace-proxies.txt Wed Jun 23 13:35:23 2010 @@ -610,7 +610,7 @@ .. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py .. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py .. _`transparent.py`: ../../pypy/objspace/std/transparent.py -.. _`tputil.py`: ../../lib/pypy1.2/lib_pypy/tputil.py +.. _`tputil.py`: ../../lib_pypy/tputil.py .. [D12.1] `High-Level Backends and Interpreter Feature Prototypes`, PyPy EU-Report, 2007, http://codespeak.net/pypy/extradoc/eu-report/D12.1_H-L-Backends_and_Feature_Prototypes-2007-03-22.pdf From arigo at codespeak.net Wed Jun 23 14:17:12 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jun 2010 14:17:12 +0200 (CEST) Subject: [pypy-svn] r75523 - pypy/trunk/pypy/translator/backendopt/test Message-ID: <20100623121712.84F9B282BAD@codespeak.net> Author: arigo Date: Wed Jun 23 14:17:11 2010 New Revision: 75523 Modified: pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py Log: This is a completely random fix. As the test starts failing from r75472, which does an unrelated change to the implementation of time.clock(), I can only imagine that it changes the expected result here (pystone calls time.clock too). I did not investigate why we get 16 instead of 10. Modified: pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py Wed Jun 23 14:17:11 2010 @@ -169,7 +169,7 @@ t, graph = rtype(entrypoint, [int]) total0 = preparation(t, t.graphs, heuristic=heuristic) total = clever_inlining_and_malloc_removal(t) - assert total0 + total == 10 + assert total0 + total == 16 def test_richards(): from pypy.translator.goal.richards import entry_point From arigo at codespeak.net Wed Jun 23 14:41:59 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jun 2010 14:41:59 +0200 (CEST) Subject: [pypy-svn] r75524 - in pypy/trunk/pypy/objspace/std: . test Message-ID: <20100623124159.3159B282BAD@codespeak.net> Author: arigo Date: Wed Jun 23 14:41:57 2010 New Revision: 75524 Modified: pypy/trunk/pypy/objspace/std/floatobject.py pypy/trunk/pypy/objspace/std/test/test_floatobject.py Log: Special-case explicitly inf and nan in str(float). At least this gives consistent answers, and fixes the previous string, which was of the kind "nan.0" for no good reason. Modified: pypy/trunk/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/pypy/objspace/std/floatobject.py Wed Jun 23 14:41:57 2010 @@ -77,23 +77,34 @@ def float_w__Float(space, w_float): return w_float.floatval -def should_not_look_like_an_int(s): - for c in s: - if c in '.eE': - break +def float2string(space, w_float, format): + x = w_float.floatval + # we special-case explicitly inf and nan here + if isinf(x): + if x > 0.0: + s = "inf" + else: + s = "-inf" + elif isnan(x): + s = "nan" else: - s += '.0' - return s + s = formatd(format, x) + # We want float numbers to be recognizable as such, + # i.e., they should contain a decimal point or an exponent. + # However, %g may print the number as an integer; + # in such cases, we append ".0" to the string. + for c in s: + if c in '.eE': + break + else: + s += '.0' + return space.wrap(s) def repr__Float(space, w_float): - x = w_float.floatval - s = formatd("%.17g", x) - return space.wrap(should_not_look_like_an_int(s)) + return float2string(space, w_float, "%.17g") def str__Float(space, w_float): - x = w_float.floatval - s = formatd("%.12g", x) - return space.wrap(should_not_look_like_an_int(s)) + return float2string(space, w_float, "%.12g") # ____________________________________________________________ # A mess to handle all cases of float comparison without relying Modified: pypy/trunk/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_floatobject.py Wed Jun 23 14:41:57 2010 @@ -95,7 +95,14 @@ inf = 1e200*1e200 assert float("inf") == inf assert float("-INf") == -inf - assert 'nan' in str(float("-nAn")).lower() + assert str(inf) == "inf" + assert str(-inf) == "-inf" + assert str(float("nan")) == "nan" + assert str(float("-nAn")) == "nan" + assert repr(inf) == "inf" + assert repr(-inf) == "-inf" + assert repr(float("nan")) == "nan" + assert repr(float("-nAn")) == "nan" def test_float_unicode(self): # u00A0 and u2000 are some kind of spaces From arigo at codespeak.net Wed Jun 23 15:07:15 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jun 2010 15:07:15 +0200 (CEST) Subject: [pypy-svn] r75525 - pypy/trunk/pypy/objspace/std Message-ID: <20100623130715.047C936C539@codespeak.net> Author: arigo Date: Wed Jun 23 15:07:14 2010 New Revision: 75525 Modified: pypy/trunk/pypy/objspace/std/floatobject.py Log: Remove the tabs (thanks Amaury). Modified: pypy/trunk/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/pypy/objspace/std/floatobject.py Wed Jun 23 15:07:14 2010 @@ -90,9 +90,9 @@ else: s = formatd(format, x) # We want float numbers to be recognizable as such, - # i.e., they should contain a decimal point or an exponent. - # However, %g may print the number as an integer; - # in such cases, we append ".0" to the string. + # i.e., they should contain a decimal point or an exponent. + # However, %g may print the number as an integer; + # in such cases, we append ".0" to the string. for c in s: if c in '.eE': break From arigo at codespeak.net Wed Jun 23 15:09:44 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jun 2010 15:09:44 +0200 (CEST) Subject: [pypy-svn] r75526 - pypy/trunk/pypy/module/cpyext/test Message-ID: <20100623130944.CF5B736C53A@codespeak.net> Author: arigo Date: Wed Jun 23 15:09:43 2010 New Revision: 75526 Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Log: Disable "-Werror=implicit-function-declaration" on e.g. Mac OS/X in the test too. Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Wed Jun 23 15:09:43 2010 @@ -160,7 +160,8 @@ kwds["compile_extra"] = ["/we4013"] else: kwds["link_files"] = [str(api_library + '.so')] - kwds["compile_extra"] = ["-Werror=implicit-function-declaration"] + if sys.platform == 'linux2': + kwds["compile_extra"]=["-Werror=implicit-function-declaration"] return compile_module(name, **kwds) From arigo at codespeak.net Wed Jun 23 15:31:47 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jun 2010 15:31:47 +0200 (CEST) Subject: [pypy-svn] r75527 - in pypy/trunk/pypy/translator/c: src test Message-ID: <20100623133147.5B86536C227@codespeak.net> Author: arigo Date: Wed Jun 23 15:31:45 2010 New Revision: 75527 Modified: pypy/trunk/pypy/translator/c/src/support.h pypy/trunk/pypy/translator/c/test/test_typed.py Log: Test and fix on platforms where CPython's unichar size differs from a wchar_t. This is also a fix for test_nonmoving_unicode in pypy.rpython.lltypesystem.test.test_rffi. Modified: pypy/trunk/pypy/translator/c/src/support.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/support.h (original) +++ pypy/trunk/pypy/translator/c/src/support.h Wed Jun 23 15:31:45 2010 @@ -26,7 +26,7 @@ PyString_FromStringAndSize(_RPyString_AsString(rpystr), RPyString_Size(rpystr)) #define PyUnicode_FromRPyUnicode(rpystr) \ - PyUnicode_FromUnicode(_RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) + _PyUnicode_FromRPyUnicode(_RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) #define PyString_ToRPyString(s, rpystr) \ memcpy(_RPyString_AsString(rpystr), PyString_AS_STRING(s), \ @@ -128,6 +128,7 @@ PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index); int PyTuple_SetItem_WithIncref(PyObject *tuple, int index, PyObject *o); int PySequence_Contains_with_exc(PyObject *seq, PyObject *ob); +PyObject* _PyUnicode_FromRPyUnicode(wchar_t *items, long length); /* implementations */ @@ -501,6 +502,17 @@ return ret; } +PyObject* _PyUnicode_FromRPyUnicode(wchar_t *items, long length) +{ + PyObject *u = PyUnicode_FromUnicode(NULL, length); + long i; + for (i=0; i Author: antocuni Date: Wed Jun 23 16:31:07 2010 New Revision: 75528 Added: pypy/branch/sys-prefix/pypy/module/conftest.py (contents, props changed) Log: when running py.test pypy/module/test_lib_pypy, also collect the tests in lib_pypy Added: pypy/branch/sys-prefix/pypy/module/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/sys-prefix/pypy/module/conftest.py Wed Jun 23 16:31:07 2010 @@ -0,0 +1,17 @@ +import py +from pypy.tool.lib_pypy import LIB_PYPY + +class MultipleDirCollector(py.test.collect.Collector): + def __init__(self, name, fspaths, parent=None, config=None): + super(MultipleDirCollector, self).__init__(name, parent, config) + self.collectors = [py.test.collect.Directory(fspath, self) + for fspath in fspaths] + + def collect(self): + return self.collectors + + +def pytest_collect_directory(path, parent): + if path.basename == 'test_lib_pypy': + # collect all the test in BOTH test_lib_pypy and ../../lib_pypy + return MultipleDirCollector(path.basename, [path, LIB_PYPY], parent) From getxsick at codespeak.net Wed Jun 23 18:43:28 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Wed, 23 Jun 2010 18:43:28 +0200 (CEST) Subject: [pypy-svn] r75529 - in pypy/branch/fast-ctypes/pypy: module/jitffi rlib Message-ID: <20100623164328.5D38E282BAD@codespeak.net> Author: getxsick Date: Wed Jun 23 18:43:26 2010 New Revision: 75529 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Log: add a new class pypy.rlib.rjitffi._LibHandler update W_LibHandler to intherit from the provided class this is a better version of in r75508 Modified: pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/module/jitffi/interp_jitffi.py Wed Jun 23 18:43:26 2010 @@ -1,18 +1,16 @@ -from pypy.rlib import rdynload from pypy.rlib import rjitffi from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import OperationError, wrap_oserror from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef -class W_LibHandler(Wrappable): +class W_LibHandler(Wrappable, rjitffi._LibHandler): def __init__(self, space, name): - try: - self.handler = rdynload.dlopen(name) - except rdynload.DLOpenError, e: - raise OSError('%s: %s', name, e.msg or 'unspecified error') - self.space = space + try: + rjitffi._LibHandler.__init__(self, name) + except OSError, e: + raise OperationError(space.w_OSError, space.wrap(str(e))) def W_LibHandler___new__(space, w_type, name): try: Modified: pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py ============================================================================== --- pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py (original) +++ pypy/branch/fast-ctypes/pypy/rlib/rjitffi.py Wed Jun 23 18:43:26 2010 @@ -9,10 +9,7 @@ class CDLL(object): def __init__(self, name, load=True): if load: - try: - self.lib = rdynload.dlopen(name) - except rdynload.DLOpenError, e: - raise OSError('%s: %s', name, e.msg or 'unspecified error') + self.lib = _LibHandler(name) else: self.lib = None @@ -22,17 +19,20 @@ def get(self, func, args_type, res_type='void'): return _Get(self.cpu, self.lib, func, args_type, res_type) +class _LibHandler(object): + def __init__(self, name): + try: + self.handler = rdynload.dlopen(name) + except rdynload.DLOpenError, e: + raise OSError('%s: %s', name, e.msg or 'unspecified error') + class _Get(object): def __init__(self, cpu, lib, func, args_type, res_type='void'): assert isinstance(args_type, list) self.args_type = args_type self.res_type = res_type self.cpu = cpu - - if hasattr(lib, 'handler'): # XXX dirty hack for pypy.module.jitffi - self.lib = lib.handler - else: - self.lib = lib + self.lib = lib.handler if self.res_type == 'int': self.bres = BoxInt() From fijal at codespeak.net Wed Jun 23 18:51:39 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Jun 2010 18:51:39 +0200 (CEST) Subject: [pypy-svn] r75530 - pypy/build/bot2/pypybuildbot Message-ID: <20100623165139.86C8E282BAD@codespeak.net> Author: fijal Date: Wed Jun 23 18:51:37 2010 New Revision: 75530 Modified: pypy/build/bot2/pypybuildbot/master.py Log: Remove --jit-debug=steps from buildbot, I don't think we need it Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Wed Jun 23 18:51:37 2010 @@ -73,8 +73,7 @@ app_tests=True) jit_translation_args = ['-Ojit', '--gc=hybrid', - '--gcrootfinder=asmgcc', - '--jit-debug=steps'] + '--gcrootfinder=asmgcc'] pypyJITTranslatedTestFactory = pypybuilds.Translated( translationArgs=jit_translation_args, From benjamin at codespeak.net Wed Jun 23 19:02:32 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 19:02:32 +0200 (CEST) Subject: [pypy-svn] r75531 - pypy/branch/fast-forward/pypy/interpreter Message-ID: <20100623170232.8EE6B282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 19:02:31 2010 New Revision: 75531 Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Log: move cpython opcodes to CPythonFrame Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Wed Jun 23 19:02:31 2010 @@ -814,18 +814,6 @@ next_instr += jumpby return next_instr - def JUMP_IF_FALSE(self, stepby, next_instr): - w_cond = self.peekvalue() - if not self.space.is_true(w_cond): - next_instr += stepby - return next_instr - - def JUMP_IF_TRUE(self, stepby, next_instr): - w_cond = self.peekvalue() - if self.space.is_true(w_cond): - next_instr += stepby - return next_instr - def POP_JUMP_IF_FALSE(self, target, next_instr): w_value = self.popvalue() if not self.space.is_true(w_value): @@ -1030,6 +1018,7 @@ ofs = self.last_instr c = self.pycode.co_code[ofs] name = self.pycode.co_name + self.pycode.dump() raise BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" % (ofs, ord(c), name) ) @@ -1043,7 +1032,19 @@ raise BytecodeCorruption -class __extends__(pyframe.CPythonFrame): +class __extend__(pyframe.CPythonFrame): + + def JUMP_IF_FALSE(self, stepby, next_instr): + w_cond = self.peekvalue() + if not self.space.is_true(w_cond): + next_instr += stepby + return next_instr + + def JUMP_IF_TRUE(self, stepby, next_instr): + w_cond = self.peekvalue() + if self.space.is_true(w_cond): + next_instr += stepby + return next_instr def BUILD_MAP(self, itemcount, next_instr): if sys.version_info >= (2, 6): From benjamin at codespeak.net Wed Jun 23 19:26:55 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 19:26:55 +0200 (CEST) Subject: [pypy-svn] r75532 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100623172655.EDF2836C53A@codespeak.net> Author: benjamin Date: Wed Jun 23 19:26:54 2010 New Revision: 75532 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py Log: must indicate that this is absolute Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Wed Jun 23 19:26:54 2010 @@ -851,7 +851,7 @@ self.emit_op(ops.ROT_THREE) op_kind = compare_operations(comp.ops[i - 1]) self.emit_op_arg(ops.COMPARE_OP, op_kind) - self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup) + self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup, True) if i < (ops_count - 1): comp.comparators[i].walkabout(self) comp.comparators[-1].walkabout(self) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jun 23 19:26:54 2010 @@ -130,6 +130,9 @@ expected = eval("0 %s 11" % operator) yield self.simple_test, "x = 0 %s 11" % operator, "x", expected + def test_compare(self): + yield self.st, "x = 2; y = 5; y; h = 1 < x >= 3 < x", "h", False + def test_augmented_assignment(self): for operator in ['+', '-', '*', '**', '/', '&', '|', '^', '//', '<<', '>>']: From benjamin at codespeak.net Wed Jun 23 20:55:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 20:55:09 +0200 (CEST) Subject: [pypy-svn] r75533 - in pypy/branch/fast-forward/pypy/module/__builtin__: . test Message-ID: <20100623185509.A6C38282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 20:55:07 2010 New Revision: 75533 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py Log: __enter__ and __exit__ as real special methods for old-style classes Modified: pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py Wed Jun 23 20:55:07 2010 @@ -662,10 +662,15 @@ if w_func is not None: space.call_function(w_func) + def descr_exit(self, space, w_type, w_value, w_tb): + w_func = self.getattr(space, space.wrap('__exit__'), False) + if w_func is not None: + return space.call_function(w_func, w_type, w_value, w_tb) + rawdict = {} # unary operations -for op in "neg pos abs invert int long float oct hex".split(): +for op in "neg pos abs invert int long float oct hex enter".split(): specialname = "__%s__" % (op, ) # fool the gateway logic by giving it a real unbound method meth = new.instancemethod( @@ -755,6 +760,8 @@ __weakref__ = make_weakref_descr(W_InstanceObject), __del__ = interp2app(W_InstanceObject.descr_del, unwrap_spec=['self', ObjSpace]), + __exit__ = interp2app(W_InstanceObject.descr_exit, + unwrap_spec=['self', ObjSpace, W_Root, W_Root, W_Root]), **rawdict ) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py Wed Jun 23 20:55:07 2010 @@ -767,6 +767,19 @@ finally: warnings.simplefilter('default', RuntimeWarning) + def test_context_manager(self): + class Context: + def __enter__(self): + self.got_enter = True + return 23 + def __exit__(self, exc, value, tp): + self.got_exit = True + c = Context() + with c as a: + assert c.got_enter + assert a == 23 + assert c.got_exit + class AppTestOldStyleSharing(AppTestOldstyle): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) From benjamin at codespeak.net Wed Jun 23 21:30:34 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 21:30:34 +0200 (CEST) Subject: [pypy-svn] r75534 - in pypy/branch/fast-forward/pypy/interpreter: . astcompiler Message-ID: <20100623193034.29386282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 21:30:30 2010 New Revision: 75534 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Log: implement SETUP_WITH opcode Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py Wed Jun 23 21:30:30 2010 @@ -314,7 +314,8 @@ if jump_op == ops.FOR_ITER: target_depth -= 2 elif (jump_op == ops.SETUP_FINALLY or - jump_op == ops.SETUP_EXCEPT): + jump_op == ops.SETUP_EXCEPT or + jump_op == ops.SETUP_WITH): target_depth += 3 if target_depth > max_depth: max_depth = target_depth @@ -500,6 +501,7 @@ ops.WITH_CLEANUP : -1, ops.POP_BLOCK : 0, ops.END_FINALLY : -3, + ops.SETUP_WITH : 1, ops.SETUP_FINALLY : 0, ops.SETUP_EXCEPT : 0, Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Wed Jun 23 21:30:30 2010 @@ -707,35 +707,20 @@ self.update_position(wih.lineno, True) body_block = self.new_block() cleanup = self.new_block() - exit_storage = self.current_temporary_name() - temp_result = None - if wih.optional_vars: - temp_result = self.current_temporary_name() wih.context_expr.walkabout(self) - self.emit_op(ops.DUP_TOP) - self.emit_op_name(ops.LOAD_ATTR, self.names, "__exit__") - self.name_op(exit_storage, ast.Store) - self.emit_op_name(ops.LOAD_ATTR, self.names, "__enter__") - self.emit_op_arg(ops.CALL_FUNCTION, 0) - if wih.optional_vars: - self.name_op(temp_result, ast.Store) - else: - self.emit_op(ops.POP_TOP) - self.emit_jump(ops.SETUP_FINALLY, cleanup) + self.emit_jump(ops.SETUP_WITH, cleanup) self.use_next_block(body_block) self.push_frame_block(F_BLOCK_FINALLY, body_block) if wih.optional_vars: - self.name_op(temp_result, ast.Load) - self.name_op(temp_result, ast.Del) wih.optional_vars.walkabout(self) + else: + self.emit_op(ops.POP_TOP) self.visit_sequence(wih.body) self.emit_op(ops.POP_BLOCK) self.pop_frame_block(F_BLOCK_FINALLY, body_block) self.load_const(self.space.w_None) self.use_next_block(cleanup) self.push_frame_block(F_BLOCK_FINALLY_END, cleanup) - self.name_op(exit_storage, ast.Load) - self.name_op(exit_storage, ast.Del) self.emit_op(ops.WITH_CLEANUP) self.emit_op(ops.END_FINALLY) self.pop_frame_block(F_BLOCK_FINALLY_END, cleanup) Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Wed Jun 23 21:30:30 2010 @@ -874,25 +874,47 @@ block = FinallyBlock(self, next_instr + offsettoend) self.append_block(block) + def SETUP_WITH(self, offsettoend, next_instr): + w_manager = self.peekvalue() + w_descr = self.space.lookup(w_manager, "__exit__") + if w_descr is None: + raise OperationError(self.space.w_AttributeError, + self.space.wrap("__exit__")) + w_exit = self.space.get(w_descr, w_manager) + self.settopvalue(w_exit) + w_enter = self.space.lookup(w_manager, "__enter__") + if w_enter is None: + raise OperationError(self.space.w_AttributeError, + self.space.wrap("__enter__")) + w_result = self.space.get_and_call_function(w_enter, w_manager) + block = FinallyBlock(self, next_instr + offsettoend) + self.append_block(block) + self.pushvalue(w_result) + def WITH_CLEANUP(self, oparg, next_instr): - # see comment in END_FINALLY for stack state - w_exitfunc = self.popvalue() - w_unroller = self.peekvalue(2) + self.dropvalues(2) + w_unroller = self.popvalue() unroller = self.space.interpclass_w(w_unroller) - if isinstance(unroller, SApplicationException): + w_exit = self.popvalue() + is_app_exc = (unroller is not None and + isinstance(unroller, SApplicationException)) + if is_app_exc: operr = unroller.operr - w_result = self.space.call_function(w_exitfunc, - operr.w_type, - operr.get_w_value(self.space), - operr.application_traceback) - if self.space.is_true(w_result): - # __exit__() returned True -> Swallow the exception. - self.settopvalue(self.space.w_None, 2) - else: - self.space.call_function(w_exitfunc, - self.space.w_None, - self.space.w_None, - self.space.w_None) + w_type = operr.w_type + w_value = operr.get_w_value(self.space) + w_tb = self.space.wrap(operr.application_traceback) + else: + w_type = w_value = w_tb = self.space.w_None + w_suppress = self.space.call_function(w_exit, w_type, w_value, w_tb) + if is_app_exc and self.space.is_true(w_suppress): + self.pushvalue(self.space.w_None) + self.pushvalue(self.space.w_None) + self.pushvalue(self.space.w_None) + else: + self.pushvalue(w_unroller) + self.pushvalue(w_value) + self.pushvalue(w_type) + print self.valuestack_w @jit.unroll_safe def call_function(self, oparg, w_star=None, w_starstar=None): From benjamin at codespeak.net Wed Jun 23 21:35:28 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 21:35:28 +0200 (CEST) Subject: [pypy-svn] r75535 - pypy/branch/fast-forward/pypy/module/__builtin__/test Message-ID: <20100623193528.E10E4282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 21:35:27 2010 New Revision: 75535 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Log: fix intention of test Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Wed Jun 23 21:35:27 2010 @@ -524,7 +524,7 @@ pr("Hello", file=None) # This works. out = StringIO.StringIO() pr(None, file=out) - assert out.getvalue == "None" + assert out.getvalue() == "None\n" def test_print_exceptions(self): import __builtin__ From benjamin at codespeak.net Wed Jun 23 21:41:01 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 21:41:01 +0200 (CEST) Subject: [pypy-svn] r75536 - pypy/branch/fast-forward/pypy/interpreter Message-ID: <20100623194101.D7181282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 21:41:00 2010 New Revision: 75536 Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Log: remove print Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Wed Jun 23 21:41:00 2010 @@ -914,7 +914,6 @@ self.pushvalue(w_unroller) self.pushvalue(w_value) self.pushvalue(w_type) - print self.valuestack_w @jit.unroll_safe def call_function(self, oparg, w_star=None, w_starstar=None): From benjamin at codespeak.net Wed Jun 23 21:51:07 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 21:51:07 +0200 (CEST) Subject: [pypy-svn] r75537 - pypy/branch/fast-forward/pypy/interpreter/pyparser/data Message-ID: <20100623195107.4D2BB282BAD@codespeak.net> Author: benjamin Date: Wed Jun 23 21:51:05 2010 New Revision: 75537 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Log: rip out old comments Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Wed Jun 23 21:51:05 2010 @@ -10,18 +10,6 @@ # NOTE WELL: You should also follow all the steps listed in PEP 306, # "How to Change Python's Grammar" -# Commands for Kees Blom's railroad program -#diagram:token NAME -#diagram:token NUMBER -#diagram:token STRING -#diagram:token NEWLINE -#diagram:token ENDMARKER -#diagram:token INDENT -#diagram:output\input python.bla -#diagram:token DEDENT -#diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm -#diagram:rules - # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; From benjamin at codespeak.net Wed Jun 23 22:03:17 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 22:03:17 +0200 (CEST) Subject: [pypy-svn] r75538 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler astcompiler/test pyparser/data test Message-ID: <20100623200317.EE957282BD6@codespeak.net> Author: benjamin Date: Wed Jun 23 22:03:16 2010 New Revision: 75538 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: implement multi-with statements Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Wed Jun 23 22:03:16 2010 @@ -436,15 +436,23 @@ try_node.column) def handle_with_stmt(self, with_node): - test = self.handle_expr(with_node.children[1]) body = self.handle_suite(with_node.children[-1]) - if len(with_node.children) == 5: - target_node = with_node.children[2] - target = self.handle_expr(target_node.children[1]) - self.set_context(target, ast.Store) - else: - target = None - return ast.With(test, target, body, with_node.lineno, with_node.column) + i = len(with_node.children) - 1 + while True: + i -= 2 + item = with_node.children[i] + test = self.handle_expr(item.children[0]) + if len(item.children) == 3: + target = self.handle_expr(item.children[2]) + self.set_context(target, ast.Store) + else: + target = None + wi = ast.With(test, target, body, with_node.lineno, + with_node.column) + if i == 1: + break + body = [wi] + return wi def handle_classdef(self, classdef_node, decorators=None): name_node = classdef_node.children[1] Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Wed Jun 23 22:03:16 2010 @@ -455,6 +455,20 @@ assert wi.optional_vars.elts[0].ctx == ast.Store input = "with x hi y: pass" exc = py.test.raises(SyntaxError, self.get_ast, input).value + wi = self.get_first_stmt("with x as y, b: pass") + assert isinstance(wi, ast.With) + assert isinstance(wi.context_expr, ast.Name) + assert wi.context_expr.id == "x" + assert isinstance(wi.optional_vars, ast.Name) + assert wi.optional_vars.id == "y" + assert len(wi.body) == 1 + wi = wi.body[0] + assert isinstance(wi, ast.With) + assert isinstance(wi.context_expr, ast.Name) + assert wi.context_expr.id == "b" + assert wi.optional_vars is None + assert len(wi.body) == 1 + assert isinstance(wi.body[0], ast.Pass) def test_class(self): for input in ("class X: pass", "class X(): pass"): Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Wed Jun 23 22:03:16 2010 @@ -71,8 +71,8 @@ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) -with_stmt: 'with' test [ with_var ] ':' suite -with_var: 'as' expr +with_stmt: 'with' with_item (',' with_item)* ':' suite +with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [('as' | ',') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Wed Jun 23 22:03:16 2010 @@ -390,6 +390,30 @@ assert acontext.calls == '__enter__ __exit__'.split() + def test_compound_with(self): + s = """class Context: + def __init__(self, var): + self.record = [] + self.var = a + def __enter__(self): + self.record.append(("__enter__", self.var)) + return self.var + def __exit__(self): + self.record.append(("__exit__", self.var)) +c1 = Context("blah") +c2 = Context("bling") +with c1 as v1, c2 as v2: + pass + """ + ns = {} + exec s in ns + assert ns["v1"] == "blah" + assert ns["v2"] == "bling" + assert ns["c1"].record == [("__enter__", "blah"), ("__exit__", "blah")] + assert ns["c2"].record == [("__exit___", "bling"), + ("__exit__", "bling")] + + def test_start_with_blank_line(self): s = """ if 1: From benjamin at codespeak.net Wed Jun 23 22:16:16 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 23 Jun 2010 22:16:16 +0200 (CEST) Subject: [pypy-svn] r75539 - pypy/branch/fast-forward/pypy/interpreter Message-ID: <20100623201616.BE8B1282BD6@codespeak.net> Author: benjamin Date: Wed Jun 23 22:16:14 2010 New Revision: 75539 Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Log: give with its own block to ensure exception normalization Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Wed Jun 23 22:16:14 2010 @@ -887,7 +887,7 @@ raise OperationError(self.space.w_AttributeError, self.space.wrap("__enter__")) w_result = self.space.get_and_call_function(w_enter, w_manager) - block = FinallyBlock(self, next_instr + offsettoend) + block = WithBlock(self, next_instr + offsettoend) self.append_block(block) self.pushvalue(w_result) @@ -1317,6 +1317,15 @@ return self.handlerposition # jump to the handler +class WithBlock(FinallyBlock): + + def really_handle(self, frame, unroller): + if (frame.space.full_exceptions and + isinstance(unroller, SApplicationException)): + unroller.operr.normalize_exception(frame.space) + return FinallyBlock.really_handle(self, frame, unroller) + + block_classes = {'SETUP_LOOP': LoopBlock, 'SETUP_EXCEPT': ExceptBlock, 'SETUP_FINALLY': FinallyBlock} From jcreigh at codespeak.net Wed Jun 23 23:38:22 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 23 Jun 2010 23:38:22 +0200 (CEST) Subject: [pypy-svn] r75540 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100623213822.83DC8282BAD@codespeak.net> Author: jcreigh Date: Wed Jun 23 23:38:20 2010 New Revision: 75540 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: a few misc new encodings for rx86 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Wed Jun 23 23:38:20 2010 @@ -435,6 +435,7 @@ CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) CMP_rm = insn(rex_w, '\x3B', register(1, 8), mem_reg_plus_const(2)) + CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) AND8_rr = insn(rex_w, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -488,6 +489,7 @@ XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') JMP_l = insn('\xE9', relative(1)) + JMP_r = insn(rex_nw, '\xFF', orbyte(4<<3), register(1), '\xC0') # FIXME: J_il8 and JMP_l8 assume the caller will do the appropriate # calculation to find the displacement, but J_il does it for the caller. # We need to be consistent. @@ -540,6 +542,8 @@ 'NLE': 15, 'G': 15, } +def invert_condition(cond_num): + return cond_num ^ 1 class X86_32_CodeBuilder(AbstractX86CodeBuilder): WORD = 4 @@ -572,6 +576,7 @@ # MOV_ri from the parent class is not wrong, but here is a better encoding # for the common case where the immediate fits in 32 bits _MOV_ri32 = insn(rex_w, '\xC7', register(1), '\xC0', immediate(2, 'i')) + MOV_ri64 = AbstractX86CodeBuilder.MOV_ri def MOV_ri(self, reg, immed): if fits_in_32bits(immed): From jcreigh at codespeak.net Wed Jun 23 23:39:01 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 23 Jun 2010 23:39:01 +0200 (CEST) Subject: [pypy-svn] r75541 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100623213901.27E5B282BAD@codespeak.net> Author: jcreigh Date: Wed Jun 23 23:38:59 2010 New Revision: 75541 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: get rid of mc2 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Wed Jun 23 23:38:59 2010 @@ -108,9 +108,15 @@ if name.upper() == name or name == "writechr": setattr(MachineCodeBlockWrapper, name, _new_method(name)) +class GuardToken(object): + def __init__(self, faildescr, failargs, fail_locs, exc): + self.faildescr = faildescr + self.failargs = failargs + self.fail_locs = fail_locs + self.exc = exc + class Assembler386(object): mc = None - mc2 = None mc_size = MachineCodeBlockWrapper.MC_DEFAULT_SIZE _float_constants = None _regalloc = None @@ -133,6 +139,7 @@ self.float_const_abs_addr = 0 self.malloc_fixedsize_slowpath1 = 0 self.malloc_fixedsize_slowpath2 = 0 + self.pending_guard_tokens = [] self.setup_failure_recovery() def leave_jitted_hook(self): @@ -167,11 +174,7 @@ self.assembler_helper_adr = self.cpu.cast_ptr_to_int( self.cpu.assembler_helper_ptr) - # done - # we generate the loop body in 'mc' - # 'mc2' is for guard recovery code self.mc = MachineCodeBlockWrapper(self.mc_size, self.cpu.profile_agent) - self.mc2 = MachineCodeBlockWrapper(self.mc_size) self._build_failure_recovery(False) self._build_failure_recovery(True) if self.cpu.supports_floats: @@ -200,7 +203,7 @@ self.float_const_abs_addr = float_constants + 16 def _build_malloc_fixedsize_slowpath(self): - mc = self.mc2._mc + mc = self.mc._mc # ---------- first helper for the slow path of malloc ---------- self.malloc_fixedsize_slowpath1 = mc.tell() if self.cpu.supports_floats: # save the XMM registers in @@ -223,7 +226,7 @@ nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX mc.RET() - self.mc2.done() + self.mc.done() def assemble_loop(self, inputargs, operations, looptoken): """adds the following attributes to looptoken: @@ -237,6 +240,7 @@ funcname = self._find_debug_merge_point(operations) self.make_sure_mc_exists() + regalloc = RegAlloc(self, self.cpu.translate_support_code) arglocs = regalloc.prepare_loop(inputargs, operations, looptoken) looptoken._x86_arglocs = arglocs @@ -268,8 +272,8 @@ debug_print("Loop #", looptoken.number, "has address", looptoken._x86_loop_code, "to", self.mc.tell()) self.mc.end_function() + self.write_pending_failure_recoveries() - def assemble_bridge(self, faildescr, inputargs, operations): funcname = self._find_debug_merge_point(operations) @@ -303,6 +307,14 @@ descr_number, "has address", adr_bridge, "to", self.mc.tell()) self.mc.end_function() + self.write_pending_failure_recoveries() + + def write_pending_failure_recoveries(self): + for tok in self.pending_guard_tokens: + addr = self.generate_quick_failure(tok.faildescr, tok.failargs, tok.fail_locs, tok.exc) + self.patch_jump_for_descr(tok.faildescr, addr) + + self.pending_guard_tokens = [] def _find_debug_merge_point(self, operations): for op in operations: @@ -321,7 +333,6 @@ self._regalloc = regalloc regalloc.walk_operations(operations) self.mc.done() - self.mc2.done() if we_are_translated() or self.cpu.dont_keepalive_stuff: self._regalloc = None # else keep it around for debugging frame_depth = regalloc.fm.frame_depth @@ -554,14 +565,15 @@ faildescr._x86_current_depths = current_depths failargs = guard_op.fail_args guard_opnum = guard_op.opnum - failaddr = self.implement_guard_recovery(guard_opnum, - faildescr, failargs, - faillocs) + guard_token = self.implement_guard_recovery(guard_opnum, + faildescr, failargs, + faillocs) + self.pending_guard_tokens.append(guard_token) if op is None: dispatch_opnum = guard_opnum else: dispatch_opnum = op.opnum - res = genop_guard_list[dispatch_opnum](self, op, guard_op, failaddr, + res = genop_guard_list[dispatch_opnum](self, op, guard_op, guard_token, arglocs, resloc) faildescr._x86_adr_jump_offset = res @@ -615,24 +627,24 @@ return genop_cmp def _cmpop_guard(cond, rev_cond, false_cond, false_rev_cond): - def genop_cmp_guard(self, op, guard_op, addr, arglocs, result_loc): + def genop_cmp_guard(self, op, guard_op, guard_token, arglocs, result_loc): guard_opnum = guard_op.opnum if isinstance(op.args[0], Const): self.mc.CMP(arglocs[1], arglocs[0]) if guard_opnum == rop.GUARD_FALSE: - return self.implement_guard(addr, rev_cond) + return self.implement_guard(guard_token, rev_cond) else: - return self.implement_guard(addr, false_rev_cond) + return self.implement_guard(guard_token, false_rev_cond) else: self.mc.CMP(arglocs[0], arglocs[1]) if guard_opnum == rop.GUARD_FALSE: - return self.implement_guard(addr, cond) + return self.implement_guard(guard_token, cond) else: - return self.implement_guard(addr, false_cond) + return self.implement_guard(guard_token, false_cond) return genop_cmp_guard def _cmpop_guard_float(cond, false_cond, need_jp): - def genop_cmp_guard_float(self, op, guard_op, addr, arglocs, + def genop_cmp_guard_float(self, op, guard_op, guard_token, arglocs, result_loc): guard_opnum = guard_op.opnum self.mc.UCOMISD(arglocs[0], arglocs[1]) @@ -640,16 +652,14 @@ mc = self.mc._mc if need_jp: mc.J_il8(rx86.Conditions['P'], 6) - mc.J_il(rx86.Conditions[cond], addr) - return mc.tell() - 4 + return self.implement_guard(guard_token, cond) else: if need_jp: mc = self.mc._mc mc.J_il8(rx86.Conditions['P'], 2) mc.J_il8(rx86.Conditions[cond], 5) - mc.JMP_l(addr) - return mc.tell() - 4 - return self.implement_guard(addr, false_cond) + return self.implement_guard(guard_token) + return self.implement_guard(guard_token, false_cond) return genop_cmp_guard_float # We need to specialize on force_mc because if force_mc is True, "mc" will @@ -834,19 +844,17 @@ genop_guard_float_gt = _cmpop_guard_float("A", "BE", False) genop_guard_float_ge = _cmpop_guard_float("AE", "B", False) - def genop_guard_float_ne(self, op, guard_op, addr, arglocs, result_loc): + def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc): guard_opnum = guard_op.opnum self.mc.UCOMISD(arglocs[0], arglocs[1]) mc = self.mc._mc if guard_opnum == rop.GUARD_TRUE: mc.J_il8(rx86.Conditions['P'], 6) - mc.J_il(rx86.Conditions['E'], addr) - return mc.tell() - 4 + return self.implement_guard(guard_token, 'E') else: mc.J_il8(rx86.Conditions['P'], 2) mc.J_il8(rx86.Conditions['E'], 5) - mc.JMP_l(addr) - return mc.tell() - 4 + return self.implement_guard(guard_token) def genop_float_neg(self, op, arglocs, resloc): # Following what gcc does: res = x ^ 0x8000000000000000 @@ -862,13 +870,13 @@ def genop_cast_int_to_float(self, op, arglocs, resloc): self.mc.CVTSI2SD(resloc, arglocs[0]) - def genop_guard_int_is_true(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_true(self, op, guard_op, guard_token, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm(0)) if guard_opnum == rop.GUARD_TRUE: - return self.implement_guard(addr, 'Z') + return self.implement_guard(guard_token, 'Z') else: - return self.implement_guard(addr, 'NZ') + return self.implement_guard(guard_token, 'NZ') def genop_int_is_true(self, op, arglocs, resloc): self.mc.CMP(arglocs[0], imm(0)) @@ -876,13 +884,13 @@ self.mc.SET_ir(rx86.Conditions['NE'], rl.value) self.mc.MOVZX8(resloc, rl) - def genop_guard_int_is_zero(self, op, guard_op, addr, arglocs, resloc): + def genop_guard_int_is_zero(self, op, guard_op, guard_token, arglocs, resloc): guard_opnum = guard_op.opnum self.mc.CMP(arglocs[0], imm(0)) if guard_opnum == rop.GUARD_TRUE: - return self.implement_guard(addr, 'NZ') + return self.implement_guard(guard_token, 'NZ') else: - return self.implement_guard(addr, 'Z') + return self.implement_guard(guard_token, 'Z') def genop_int_is_zero(self, op, arglocs, resloc): self.mc.CMP(arglocs[0], imm8(0)) @@ -1072,65 +1080,65 @@ else: assert 0, itemsize - def genop_guard_guard_true(self, ign_1, guard_op, addr, locs, ign_2): + def genop_guard_guard_true(self, ign_1, guard_op, guard_token, locs, ign_2): loc = locs[0] self.mc.TEST(loc, loc) - return self.implement_guard(addr, 'Z') + return self.implement_guard(guard_token, 'Z') genop_guard_guard_nonnull = genop_guard_guard_true - def genop_guard_guard_no_exception(self, ign_1, guard_op, addr, + def genop_guard_guard_no_exception(self, ign_1, guard_op, guard_token, locs, ign_2): self.mc.CMP(heap(self.cpu.pos_exception()), imm(0)) - return self.implement_guard(addr, 'NZ') + return self.implement_guard(guard_token, 'NZ') - def genop_guard_guard_exception(self, ign_1, guard_op, addr, + def genop_guard_guard_exception(self, ign_1, guard_op, guard_token, locs, resloc): loc = locs[0] loc1 = locs[1] self.mc.MOV(loc1, heap(self.cpu.pos_exception())) self.mc.CMP(loc1, loc) - addr = self.implement_guard(addr, 'NE') + addr = self.implement_guard(guard_token, 'NE') if resloc is not None: self.mc.MOV(resloc, heap(self.cpu.pos_exc_value())) self.mc.MOV(heap(self.cpu.pos_exception()), imm(0)) self.mc.MOV(heap(self.cpu.pos_exc_value()), imm(0)) return addr - def _gen_guard_overflow(self, guard_op, addr): + def _gen_guard_overflow(self, guard_op, guard_token): guard_opnum = guard_op.opnum if guard_opnum == rop.GUARD_NO_OVERFLOW: - return self.implement_guard(addr, 'O') + return self.implement_guard(guard_token, 'O') elif guard_opnum == rop.GUARD_OVERFLOW: - return self.implement_guard(addr, 'NO') + return self.implement_guard(guard_token, 'NO') else: print "int_xxx_ovf followed by", guard_op.getopname() raise AssertionError - def genop_guard_int_add_ovf(self, op, guard_op, addr, arglocs, result_loc): + def genop_guard_int_add_ovf(self, op, guard_op, guard_token, arglocs, result_loc): self.genop_int_add(op, arglocs, result_loc) - return self._gen_guard_overflow(guard_op, addr) + return self._gen_guard_overflow(guard_op, guard_token) - def genop_guard_int_sub_ovf(self, op, guard_op, addr, arglocs, result_loc): + def genop_guard_int_sub_ovf(self, op, guard_op, guard_token, arglocs, result_loc): self.genop_int_sub(op, arglocs, result_loc) - return self._gen_guard_overflow(guard_op, addr) + return self._gen_guard_overflow(guard_op, guard_token) - def genop_guard_int_mul_ovf(self, op, guard_op, addr, arglocs, result_loc): + def genop_guard_int_mul_ovf(self, op, guard_op, guard_token, arglocs, result_loc): self.genop_int_mul(op, arglocs, result_loc) - return self._gen_guard_overflow(guard_op, addr) + return self._gen_guard_overflow(guard_op, guard_token) - def genop_guard_guard_false(self, ign_1, guard_op, addr, locs, ign_2): + def genop_guard_guard_false(self, ign_1, guard_op, guard_token, locs, ign_2): loc = locs[0] self.mc.TEST(loc, loc) - return self.implement_guard(addr, 'NZ') + return self.implement_guard(guard_token, 'NZ') genop_guard_guard_isnull = genop_guard_guard_false - def genop_guard_guard_value(self, ign_1, guard_op, addr, locs, ign_2): + def genop_guard_guard_value(self, ign_1, guard_op, guard_token, locs, ign_2): if guard_op.args[0].type == FLOAT: assert guard_op.args[1].type == FLOAT self.mc.UCOMISD(locs[0], locs[1]) else: self.mc.CMP(locs[0], locs[1]) - return self.implement_guard(addr, 'NE') + return self.implement_guard(guard_token, 'NE') def _cmp_guard_class(self, mc, locs): offset = self.cpu.vtable_offset @@ -1155,14 +1163,14 @@ expected_typeid = (classptr - sizeof_ti - type_info_group) >> 2 mc.CMP16(mem(locs[0], 0), ImmedLoc(expected_typeid)) - def genop_guard_guard_class(self, ign_1, guard_op, addr, locs, ign_2): + def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, ign_2): mc = self._start_block() self._cmp_guard_class(mc, locs) self._stop_block() - return self.implement_guard(addr, 'NE') + return self.implement_guard(guard_token, 'NE') def genop_guard_guard_nonnull_class(self, ign_1, guard_op, - addr, locs, ign_2): + guard_token, locs, ign_2): mc = self._start_block() mc.CMP(locs[0], imm8(1)) # Patched below @@ -1175,14 +1183,14 @@ mc.overwrite(jb_location-1, [chr(offset)]) self._stop_block() # - return self.implement_guard(addr, 'NE') + return self.implement_guard(guard_token, 'NE') def implement_guard_recovery(self, guard_opnum, faildescr, failargs, fail_locs): exc = (guard_opnum == rop.GUARD_EXCEPTION or guard_opnum == rop.GUARD_NO_EXCEPTION or guard_opnum == rop.GUARD_NOT_FORCED) - return self.generate_quick_failure(faildescr, failargs, fail_locs, exc) + return GuardToken(faildescr, failargs, fail_locs, exc) def generate_quick_failure(self, faildescr, failargs, fail_locs, exc): """Generate the initial code for handling a failure. We try to @@ -1193,9 +1201,9 @@ """ fail_index = self.cpu.get_fail_descr_number(faildescr) bytes_needed = 20 + 5 * len(failargs) # conservative estimate - if self.mc2.bytes_free() < bytes_needed: - self.mc2.make_new_mc() - mc = self.mc2._mc + if self.mc.bytes_free() < bytes_needed: + self.mc.make_new_mc() + mc = self.mc._mc addr = mc.tell() withfloats = False for box in failargs: @@ -1389,7 +1397,7 @@ self.failure_recovery_func) failure_recovery_func = rffi.cast(lltype.Signed, failure_recovery_func) - mc = self.mc2._mc + mc = self.mc._mc # Assume that we are called at the beginning, when there is no risk # that 'mc' runs out of space. Checked by asserts in mc.write(). recovery_addr = mc.tell() @@ -1441,9 +1449,9 @@ # _assemble_bootstrap_code(). The LEA below throws away most # of the frame, including all the PUSHes that we did just above. - # XXX: using self.mc2 instead of mc to make translation pass - self._call_footer(self.mc2) - self.mc2.done() + # XXX: using self.mc instead of mc to make translation pass + self._call_footer(self.mc) + self.mc.done() self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr def generate_failure(self, fail_index, locs, exc, locs_are_ref): @@ -1493,11 +1501,12 @@ # FIXME: I changed the third argument to this method, but I don't know # what to do with @specialize @specialize.arg(2) - def implement_guard(self, addr, condition=None): + def implement_guard(self, guard_token, condition=None): + # These jumps are patched later if condition: - self.mc.J_il(rx86.Conditions[condition], addr) + self.mc.J_il(rx86.Conditions[condition], self.mc.tell()) else: - self.mc.JMP_l(addr) + self.mc.JMP_l(self.mc.tell()) return self.mc.tell() - 4 def genop_call(self, op, arglocs, resloc): @@ -1523,16 +1532,16 @@ elif size == 2: self.mc.AND(eax, imm(0xffff)) - def genop_guard_call_may_force(self, op, guard_op, addr, + def genop_guard_call_may_force(self, op, guard_op, guard_token, arglocs, result_loc): faildescr = guard_op.descr fail_index = self.cpu.get_fail_descr_number(faildescr) self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index) self.genop_call(op, arglocs, result_loc) self.mc.CMP_bi(FORCE_INDEX_OFS, 0) - return self.implement_guard(addr, 'L') + return self.implement_guard(guard_token, 'L') - def genop_guard_call_assembler(self, op, guard_op, addr, + def genop_guard_call_assembler(self, op, guard_op, guard_token, arglocs, result_loc): faildescr = guard_op.descr fail_index = self.cpu.get_fail_descr_number(faildescr) @@ -1615,7 +1624,7 @@ mc.overwrite(jmp_location - 1, [chr(offset)]) self._stop_block() self.mc.CMP_bi(FORCE_INDEX_OFS, 0) - return self.implement_guard(addr, 'L') + return self.implement_guard(guard_token, 'L') def genop_discard_cond_call_gc_wb(self, op, arglocs): # use 'mc._mc' directly instead of 'mc', to avoid From jcreigh at codespeak.net Thu Jun 24 00:05:52 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Thu, 24 Jun 2010 00:05:52 +0200 (CEST) Subject: [pypy-svn] r75542 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100623220552.CC2A8282BAD@codespeak.net> Author: jcreigh Date: Thu Jun 24 00:05:51 2010 New Revision: 75542 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Log: some hacks to make tests pass Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Thu Jun 24 00:05:51 2010 @@ -362,7 +362,9 @@ self.cpu.compile_bridge(faildescr1, [i1b], bridge) name, address, size = agent.functions[1] assert name == "Bridge # 0: bye" - assert address == loopaddress + loopsize + # Would be exactly ==, but there are some guard failure recovery + # stubs in-between + assert address >= loopaddress + loopsize assert size >= 10 # randomish number self.cpu.set_future_value_int(0, 2) @@ -397,6 +399,8 @@ assert self.cpu.get_latest_value_int(0) == 1024 def test_overflow_guard_float_cmp(self): + # FIXME: Skipping for now + import py.test; py.test.skip() # The float comparisons on x86 tend to use small relative jumps, # which may run into trouble if they fall on the edge of a # MachineCodeBlock change. From fijal at codespeak.net Thu Jun 24 00:15:03 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jun 2010 00:15:03 +0200 (CEST) Subject: [pypy-svn] r75543 - pypy/trunk/pypy/doc Message-ID: <20100623221503.9530D282BAD@codespeak.net> Author: fijal Date: Thu Jun 24 00:15:02 2010 New Revision: 75543 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Elaborate Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Thu Jun 24 00:15:02 2010 @@ -16,9 +16,26 @@ Highlight of this release ========================= -XXX a rough list -- cpyext (some details, in particular: the extension module must be - recompiled, and typically "bug-fixed" w.r.t. refcounting) -- bugfixes -- blackhole-improvements -- minor jit improvements +* We introduce support for CPython extension modules written in C. As of now, + this support is in alpha and it's very unlikely untried modules will work + out of the box, due to missing functions or refcounting details. The support + is disable by default, so you have to do:: + + import cpyext + + before trying to import any .so file. Also, libraries are source-compatible + and not binary-compatible. That means you need to recompile binaries, using + for example:: + + python setup.py build + + Details may vary, depending on your build system. Make sure you include + the above line at the beginning of setup.py or put it in your PYTHONSTARTUP. + + This is alpha feature, it'll likely segfault, you have been warned. + +* JIT bugfixes. A lot of bugs reported for JIT and not only has been fixed + and it's stability greatly improved since 1.2 release. + +* Various JIT improvements. Various small improvements have been added to the + JIT code, together with great speedup of compiling time. From agaynor at codespeak.net Thu Jun 24 00:17:59 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Thu, 24 Jun 2010 00:17:59 +0200 (CEST) Subject: [pypy-svn] r75544 - pypy/trunk/pypy/doc Message-ID: <20100623221759.5DC5E282BAD@codespeak.net> Author: agaynor Date: Thu Jun 24 00:17:58 2010 New Revision: 75544 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Oxford comma. Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Thu Jun 24 00:17:58 2010 @@ -6,7 +6,7 @@ We're please to announce release of PyPy 1.3. This release has two major points. First of all, we stabilized the JIT compiler since 1.2 release, -answered user issues, fixed bugs and generally improved speed. +answered user issues, fixed bugs, and generally improved speed. The other point is that we're pleased to announce alpha support for loading CPython extension modules written in C. While the main point of the release From jcreigh at codespeak.net Thu Jun 24 00:33:21 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Thu, 24 Jun 2010 00:33:21 +0200 (CEST) Subject: [pypy-svn] r75545 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100623223321.54BD7282BAD@codespeak.net> Author: jcreigh Date: Thu Jun 24 00:33:19 2010 New Revision: 75545 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py Log: when testing on 64-bit, try to allocate mcs more than 32-bits apart Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/codebuf.py Thu Jun 24 00:33:19 2010 @@ -7,6 +7,7 @@ from pypy.rlib.rmmap import PTR, alloc, free from pypy.rlib.debug import make_sure_not_resized from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64 +from pypy.rlib.objectmodel import we_are_translated # XXX: Seems nasty to change the superclass of InMemoryCodeBuilder like this if IS_X86_32: @@ -141,6 +142,12 @@ def __init__(self, map_size): data = alloc(map_size) + if IS_X86_64 and not we_are_translated(): + # Hack to make sure that mcs are not within 32-bits of one + # another for testing purposes + from pypy.rlib.rmmap import hint + hint.pos += 0xFFFFFFFF + self._init(data, map_size) def __del__(self): From benjamin at codespeak.net Thu Jun 24 02:13:17 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 24 Jun 2010 02:13:17 +0200 (CEST) Subject: [pypy-svn] r75546 - pypy/trunk/pypy/doc Message-ID: <20100624001317.DCB2D282BAD@codespeak.net> Author: benjamin Date: Thu Jun 24 02:13:16 2010 New Revision: 75546 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: edit Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Thu Jun 24 02:13:16 2010 @@ -5,21 +5,21 @@ Hello. We're please to announce release of PyPy 1.3. This release has two major -points. First of all, we stabilized the JIT compiler since 1.2 release, +improvements. First of all, we stabilized the JIT compiler since 1.2 release, answered user issues, fixed bugs, and generally improved speed. -The other point is that we're pleased to announce alpha support for loading -CPython extension modules written in C. While the main point of the release -is increased stability, this part is in alpha stage and it is not yet suited -for production environments. +We're also pleased to announce alpha support for loading CPython extension +modules written in C. While the main purpose of this release is increased +stability, this feature is in alpha stage and it is not yet suited for +production environments. Highlight of this release ========================= -* We introduce support for CPython extension modules written in C. As of now, - this support is in alpha and it's very unlikely untried modules will work - out of the box, due to missing functions or refcounting details. The support - is disable by default, so you have to do:: +* We introduced support for CPython extension modules written in C. As of now, + this support is in alpha, and it's very unlikely unaltered C extensions will + work out of the box, due to missing functions or refcounting details. The + support is disable by default, so you have to do:: import cpyext @@ -32,10 +32,10 @@ Details may vary, depending on your build system. Make sure you include the above line at the beginning of setup.py or put it in your PYTHONSTARTUP. - This is alpha feature, it'll likely segfault, you have been warned. + This is alpha feature. It'll likely segfault. You have been warned! -* JIT bugfixes. A lot of bugs reported for JIT and not only has been fixed - and it's stability greatly improved since 1.2 release. +* JIT bugfixes. A lot of bugs reported for the JIT have been fixed, and its + stability greatly improved since 1.2 release. -* Various JIT improvements. Various small improvements have been added to the - JIT code, together with great speedup of compiling time. +* Various small improvements have been added to the JIT code, as well as a great + speedup of compiling time. From fijal at codespeak.net Thu Jun 24 02:16:25 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jun 2010 02:16:25 +0200 (CEST) Subject: [pypy-svn] r75547 - pypy/trunk/pypy/module/cpyext Message-ID: <20100624001625.6DDBE282BAD@codespeak.net> Author: fijal Date: Thu Jun 24 02:16:23 2010 New Revision: 75547 Modified: pypy/trunk/pypy/module/cpyext/api.py Log: Don't use absoulte path, instead use separate_module_source. Reason: hardcoded paths in makefiles are bad Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Thu Jun 24 02:16:23 2010 @@ -809,7 +809,6 @@ kwds["includes"] = ['Python.h'] # this is our Python.h # Generate definitions for global structures - struct_file = udir.join('pypy_structs.c') structs = ["#include "] for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): @@ -819,7 +818,7 @@ structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) elif typ == 'PyDateTime_CAPI*': structs.append('%s %s = NULL;' % (typ, name)) - struct_file.write('\n'.join(structs)) + struct_source = '\n'.join(structs) eci = ExternalCompilationInfo( include_dirs=include_dirs, @@ -833,9 +832,8 @@ source_dir / "bufferobject.c", source_dir / "object.c", source_dir / "cobject.c", - struct_file, ], - separate_module_sources = [code], + separate_module_sources = [code, struct_source], export_symbols=export_symbols_eci, compile_extra=compile_extra, **kwds From benjamin at codespeak.net Thu Jun 24 02:27:06 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 24 Jun 2010 02:27:06 +0200 (CEST) Subject: [pypy-svn] r75548 - in pypy/branch/fast-forward/pypy/interpreter: . astcompiler astcompiler/test astcompiler/tools pyparser/data test Message-ID: <20100624002706.7BB2A282BAD@codespeak.net> Author: benjamin Date: Thu Jun 24 02:27:03 2010 New Revision: 75548 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/asthelpers.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl pypy/branch/fast-forward/pypy/interpreter/pyopcode.py pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: breathe life into dict and set comprehensions Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py Thu Jun 24 02:27:03 2010 @@ -440,6 +440,8 @@ ops.UNARY_INVERT : 0, ops.LIST_APPEND : -1, + ops.SET_ADD : -1, + ops.MAP_ADD : -2, ops.BINARY_POWER : -1, ops.BINARY_MULTIPLY : -1, @@ -511,6 +513,7 @@ ops.YIELD_VALUE : 0, ops.BUILD_CLASS : -2, ops.BUILD_MAP : 1, + ops.BUILD_SET : 1, ops.COMPARE_OP : -1, ops.LOOKUP_METHOD : 1, Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/ast.py Thu Jun 24 02:27:03 2010 @@ -1393,6 +1393,44 @@ node.sync_app_attrs(space) +class Set(expr): + + __slots__ = ('elts', 'w_elts') + + _lineno_mask = 2 + _col_offset_mask = 4 + + def __init__(self, elts, lineno, col_offset): + self.elts = elts + self.w_elts = None + expr.__init__(self, lineno, col_offset) + self.initialization_state = 7 + + def walkabout(self, visitor): + visitor.visit_Set(self) + + def mutate_over(self, visitor): + if self.elts: + visitor._mutate_sequence(self.elts) + return visitor.visit_Set(self) + + def sync_app_attrs(self, space): + if (self.initialization_state & ~0) ^ 7: + missing_field(space, self.initialization_state, ['elts', 'lineno', 'col_offset'], 'Set') + else: + pass + w_list = self.w_elts + if w_list is not None: + list_w = space.listview(w_list) + if list_w: + self.elts = [space.interp_w(expr, w_obj) for w_obj in list_w] + else: + self.elts = None + if self.elts is not None: + for node in self.elts: + node.sync_app_attrs(space) + + class ListComp(expr): __slots__ = ('elt', 'generators', 'w_generators') @@ -1432,6 +1470,87 @@ node.sync_app_attrs(space) +class SetComp(expr): + + __slots__ = ('elt', 'generators', 'w_generators') + + _lineno_mask = 4 + _col_offset_mask = 8 + + def __init__(self, elt, generators, lineno, col_offset): + self.elt = elt + self.generators = generators + self.w_generators = None + expr.__init__(self, lineno, col_offset) + self.initialization_state = 15 + + def walkabout(self, visitor): + visitor.visit_SetComp(self) + + def mutate_over(self, visitor): + self.elt = self.elt.mutate_over(visitor) + return visitor.visit_SetComp(self) + + def sync_app_attrs(self, space): + if (self.initialization_state & ~0) ^ 15: + missing_field(space, self.initialization_state, ['elt', 'generators', 'lineno', 'col_offset'], 'SetComp') + else: + pass + self.elt.sync_app_attrs(space) + w_list = self.w_generators + if w_list is not None: + list_w = space.listview(w_list) + if list_w: + self.generators = [space.interp_w(comprehension, w_obj) for w_obj in list_w] + else: + self.generators = None + if self.generators is not None: + for node in self.generators: + node.sync_app_attrs(space) + + +class DictComp(expr): + + __slots__ = ('key', 'value', 'generators', 'w_generators') + + _lineno_mask = 8 + _col_offset_mask = 16 + + def __init__(self, key, value, generators, lineno, col_offset): + self.key = key + self.value = value + self.generators = generators + self.w_generators = None + expr.__init__(self, lineno, col_offset) + self.initialization_state = 31 + + def walkabout(self, visitor): + visitor.visit_DictComp(self) + + def mutate_over(self, visitor): + self.key = self.key.mutate_over(visitor) + self.value = self.value.mutate_over(visitor) + return visitor.visit_DictComp(self) + + def sync_app_attrs(self, space): + if (self.initialization_state & ~0) ^ 31: + missing_field(space, self.initialization_state, ['key', 'value', 'generators', 'lineno', 'col_offset'], 'DictComp') + else: + pass + self.key.sync_app_attrs(space) + self.value.sync_app_attrs(space) + w_list = self.w_generators + if w_list is not None: + list_w = space.listview(w_list) + if list_w: + self.generators = [space.interp_w(comprehension, w_obj) for w_obj in list_w] + else: + self.generators = None + if self.generators is not None: + for node in self.generators: + node.sync_app_attrs(space) + + class GeneratorExp(expr): __slots__ = ('elt', 'generators', 'w_generators') @@ -2529,8 +2648,14 @@ return self.default_visitor(node) def visit_Dict(self, node): return self.default_visitor(node) + def visit_Set(self, node): + return self.default_visitor(node) def visit_ListComp(self, node): return self.default_visitor(node) + def visit_SetComp(self, node): + return self.default_visitor(node) + def visit_DictComp(self, node): + return self.default_visitor(node) def visit_GeneratorExp(self, node): return self.default_visitor(node) def visit_Yield(self, node): @@ -2743,11 +2868,26 @@ if node.values: self.visit_sequence(node.values) + def visit_Set(self, node): + if node.elts: + self.visit_sequence(node.elts) + def visit_ListComp(self, node): node.elt.walkabout(self) if node.generators: self.visit_sequence(node.generators) + def visit_SetComp(self, node): + node.elt.walkabout(self) + if node.generators: + self.visit_sequence(node.generators) + + def visit_DictComp(self, node): + node.key.walkabout(self) + node.value.walkabout(self) + if node.generators: + self.visit_sequence(node.generators) + def visit_GeneratorExp(self, node): node.elt.walkabout(self) if node.generators: @@ -4689,6 +4829,49 @@ ) Dict.typedef.acceptable_as_base_class = False +def Set_get_elts(space, w_self): + if not w_self.initialization_state & 1: + w_err = space.wrap("attribute 'elts' has not been set") + raise OperationError(space.w_AttributeError, w_err) + if w_self.w_elts is None: + if w_self.elts is None: + w_list = space.newlist([]) + else: + list_w = [space.wrap(node) for node in w_self.elts] + w_list = space.newlist(list_w) + w_self.w_elts = w_list + return w_self.w_elts + +def Set_set_elts(space, w_self, w_new_value): + w_self.w_elts = w_new_value + w_self.initialization_state |= 1 + +_Set_field_unroller = unrolling_iterable(['elts', 'lineno', 'col_offset']) +def Set_init(space, w_self, args): + w_self = space.descr_self_interp_w(Set, w_self) + w_self.w_elts = None + args_w, kwargs_w = args.unpack() + if args_w: + if len(args_w) != 3: + w_err = space.wrap("Set constructor takes 0 or 3 positional arguments") + raise OperationError(space.w_TypeError, w_err) + i = 0 + for field in _Set_field_unroller: + space.setattr(w_self, space.wrap(field), args_w[i]) + i += 1 + for field, w_value in kwargs_w.iteritems(): + space.setattr(w_self, space.wrap(field), w_value) +Set_init.unwrap_spec = [ObjSpace, W_Root, Arguments] + +Set.typedef = typedef.TypeDef("Set", + expr.typedef, + _fields=_FieldsWrapper(['elts']), + elts=typedef.GetSetProperty(Set_get_elts, Set_set_elts, cls=Set), + __new__=interp2app(get_AST_new(Set)), + __init__=interp2app(Set_init), +) +Set.typedef.acceptable_as_base_class = False + def ListComp_get_elt(space, w_self): if not w_self.initialization_state & 1: w_err = space.wrap("attribute 'elt' has not been set") @@ -4743,6 +4926,125 @@ ) ListComp.typedef.acceptable_as_base_class = False +def SetComp_get_elt(space, w_self): + if not w_self.initialization_state & 1: + w_err = space.wrap("attribute 'elt' has not been set") + raise OperationError(space.w_AttributeError, w_err) + return space.wrap(w_self.elt) + +def SetComp_set_elt(space, w_self, w_new_value): + w_self.elt = space.interp_w(expr, w_new_value, False) + w_self.initialization_state |= 1 + +def SetComp_get_generators(space, w_self): + if not w_self.initialization_state & 2: + w_err = space.wrap("attribute 'generators' has not been set") + raise OperationError(space.w_AttributeError, w_err) + if w_self.w_generators is None: + if w_self.generators is None: + w_list = space.newlist([]) + else: + list_w = [space.wrap(node) for node in w_self.generators] + w_list = space.newlist(list_w) + w_self.w_generators = w_list + return w_self.w_generators + +def SetComp_set_generators(space, w_self, w_new_value): + w_self.w_generators = w_new_value + w_self.initialization_state |= 2 + +_SetComp_field_unroller = unrolling_iterable(['elt', 'generators', 'lineno', 'col_offset']) +def SetComp_init(space, w_self, args): + w_self = space.descr_self_interp_w(SetComp, w_self) + w_self.w_generators = None + args_w, kwargs_w = args.unpack() + if args_w: + if len(args_w) != 4: + w_err = space.wrap("SetComp constructor takes 0 or 4 positional arguments") + raise OperationError(space.w_TypeError, w_err) + i = 0 + for field in _SetComp_field_unroller: + space.setattr(w_self, space.wrap(field), args_w[i]) + i += 1 + for field, w_value in kwargs_w.iteritems(): + space.setattr(w_self, space.wrap(field), w_value) +SetComp_init.unwrap_spec = [ObjSpace, W_Root, Arguments] + +SetComp.typedef = typedef.TypeDef("SetComp", + expr.typedef, + _fields=_FieldsWrapper(['elt', 'generators']), + elt=typedef.GetSetProperty(SetComp_get_elt, SetComp_set_elt, cls=SetComp), + generators=typedef.GetSetProperty(SetComp_get_generators, SetComp_set_generators, cls=SetComp), + __new__=interp2app(get_AST_new(SetComp)), + __init__=interp2app(SetComp_init), +) +SetComp.typedef.acceptable_as_base_class = False + +def DictComp_get_key(space, w_self): + if not w_self.initialization_state & 1: + w_err = space.wrap("attribute 'key' has not been set") + raise OperationError(space.w_AttributeError, w_err) + return space.wrap(w_self.key) + +def DictComp_set_key(space, w_self, w_new_value): + w_self.key = space.interp_w(expr, w_new_value, False) + w_self.initialization_state |= 1 + +def DictComp_get_value(space, w_self): + if not w_self.initialization_state & 2: + w_err = space.wrap("attribute 'value' has not been set") + raise OperationError(space.w_AttributeError, w_err) + return space.wrap(w_self.value) + +def DictComp_set_value(space, w_self, w_new_value): + w_self.value = space.interp_w(expr, w_new_value, False) + w_self.initialization_state |= 2 + +def DictComp_get_generators(space, w_self): + if not w_self.initialization_state & 4: + w_err = space.wrap("attribute 'generators' has not been set") + raise OperationError(space.w_AttributeError, w_err) + if w_self.w_generators is None: + if w_self.generators is None: + w_list = space.newlist([]) + else: + list_w = [space.wrap(node) for node in w_self.generators] + w_list = space.newlist(list_w) + w_self.w_generators = w_list + return w_self.w_generators + +def DictComp_set_generators(space, w_self, w_new_value): + w_self.w_generators = w_new_value + w_self.initialization_state |= 4 + +_DictComp_field_unroller = unrolling_iterable(['key', 'value', 'generators', 'lineno', 'col_offset']) +def DictComp_init(space, w_self, args): + w_self = space.descr_self_interp_w(DictComp, w_self) + w_self.w_generators = None + args_w, kwargs_w = args.unpack() + if args_w: + if len(args_w) != 5: + w_err = space.wrap("DictComp constructor takes 0 or 5 positional arguments") + raise OperationError(space.w_TypeError, w_err) + i = 0 + for field in _DictComp_field_unroller: + space.setattr(w_self, space.wrap(field), args_w[i]) + i += 1 + for field, w_value in kwargs_w.iteritems(): + space.setattr(w_self, space.wrap(field), w_value) +DictComp_init.unwrap_spec = [ObjSpace, W_Root, Arguments] + +DictComp.typedef = typedef.TypeDef("DictComp", + expr.typedef, + _fields=_FieldsWrapper(['key', 'value', 'generators']), + key=typedef.GetSetProperty(DictComp_get_key, DictComp_set_key, cls=DictComp), + value=typedef.GetSetProperty(DictComp_get_value, DictComp_set_value, cls=DictComp), + generators=typedef.GetSetProperty(DictComp_get_generators, DictComp_set_generators, cls=DictComp), + __new__=interp2app(get_AST_new(DictComp)), + __init__=interp2app(DictComp_init), +) +DictComp.typedef.acceptable_as_base_class = False + def GeneratorExp_get_elt(space, w_self): if not w_self.initialization_state & 1: w_err = space.wrap("attribute 'elt' has not been set") Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Thu Jun 24 02:27:03 2010 @@ -957,7 +957,7 @@ if argument.type == syms.argument: if len(argument.children) == 1: arg_count += 1 - elif argument.children[1].type == syms.gen_for: + elif argument.children[1].type == syms.comp_for: generator_count += 1 else: keyword_count += 1 @@ -983,7 +983,7 @@ self.error("non-keyword arg after keyword arg", expr_node) args.append(self.handle_expr(expr_node)) - elif argument.children[1].type == syms.gen_for: + elif argument.children[1].type == syms.comp_for: args.append(self.handle_genexp(argument)) else: keyword_node = argument.children[0] @@ -1101,15 +1101,26 @@ atom_node.column) return self.handle_listcomp(second_child) elif first_child_type == tokens.LBRACE: - if len(atom_node.children) == 2: - return ast.Dict(None, None, atom_node.lineno, atom_node.column) - second_child = atom_node.children[1] + maker = atom_node.children[1] + if maker.type == tokens.RBRACE: + return ast.Dict(None, None, maker.lineno, maker.column) + n_maker_children = len(maker.children) + if n_maker_children == 1 or maker.children[1].type == tokens.COMMA: + elts = [] + for i in range(0, n_maker_children, 2): + elts.append(self.handle_expr(maker.children[i])) + return ast.Set(elts, maker.lineno, maker.column) + if maker.children[1].type == syms.comp_for: + return self.handle_setcomp(maker) + if (n_maker_children > 3 and + maker.children[3].type == syms.comp_for): + return self.handle_dictcomp(maker) keys = [] values = [] - for i in range(0, len(second_child.children), 4): - keys.append(self.handle_expr(second_child.children[i])) - values.append(self.handle_expr(second_child.children[i + 2])) - return ast.Dict(keys, values, atom_node.lineno, atom_node.column) + for i in range(0, n_maker_children, 4): + keys.append(self.handle_expr(maker.children[i])) + values.append(self.handle_expr(maker.children[i + 2])) + return ast.Dict(keys, values, maker.lineno, maker.column) elif first_child_type == tokens.BACKQUOTE: expr = self.handle_testlist(atom_node.children[1]) return ast.Repr(expr, atom_node.lineno, atom_node.column) @@ -1118,13 +1129,13 @@ def handle_testlist_gexp(self, gexp_node): if len(gexp_node.children) > 1 and \ - gexp_node.children[1].type == syms.gen_for: + gexp_node.children[1].type == syms.comp_for: return self.handle_genexp(gexp_node) return self.handle_testlist(gexp_node) def count_comp_fors(self, comp_node, for_type, if_type): count = 0 - current_for = comp_node.children[1] + current_for = comp_node while True: count += 1 if len(current_for.children) == 5: @@ -1155,56 +1166,70 @@ return count iter_node = first_child.children[2] - @specialize.arg(5) - def comprehension_helper(self, comp_node, for_type, if_type, iter_type, - handle_source_expression): - elt = self.handle_expr(comp_node.children[0]) + @specialize.arg(2) + def comprehension_helper(self, comp_node, + handle_source_expr_meth="handle_expr", + for_type=syms.comp_for, if_type=syms.comp_if, + iter_type=syms.comp_iter): + handle_source_expression = getattr(self, handle_source_expr_meth) fors_count = self.count_comp_fors(comp_node, for_type, if_type) comps = [] - comp_for = comp_node.children[1] for i in range(fors_count): - for_node = comp_for.children[1] + for_node = comp_node.children[1] for_targets = self.handle_exprlist(for_node, ast.Store) - expr = handle_source_expression(comp_for.children[3]) + expr = handle_source_expression(comp_node.children[3]) assert isinstance(expr, ast.expr) if len(for_node.children) == 1: comp = ast.comprehension(for_targets[0], expr, None) else: - target = ast.Tuple(for_targets, ast.Store, comp_for.lineno, - comp_for.column) + target = ast.Tuple(for_targets, ast.Store, comp_node.lineno, + comp_node.column) comp = ast.comprehension(target, expr, None) - if len(comp_for.children) == 5: - comp_for = comp_iter = comp_for.children[4] + if len(comp_node.children) == 5: + comp_node = comp_iter = comp_node.children[4] assert comp_iter.type == iter_type ifs_count = self.count_comp_ifs(comp_iter, for_type) if ifs_count: ifs = [] for j in range(ifs_count): - comp_for = comp_if = comp_iter.children[0] + comp_node = comp_if = comp_iter.children[0] ifs.append(self.handle_expr(comp_if.children[1])) if len(comp_if.children) == 3: - comp_for = comp_iter = comp_if.children[2] + comp_node = comp_iter = comp_if.children[2] comp.ifs = ifs - if comp_for.type == iter_type: - comp_for = comp_for.children[0] + if comp_node.type == iter_type: + comp_node = comp_node.children[0] assert isinstance(comp, ast.comprehension) comps.append(comp) - return elt, comps + return comps def handle_genexp(self, genexp_node): - elt, comps = self.comprehension_helper(genexp_node, syms.gen_for, - syms.gen_if, syms.gen_iter, - self.handle_expr) + elt = self.handle_expr(genexp_node.children[0]) + comps = self.comprehension_helper(genexp_node.children[1]) return ast.GeneratorExp(elt, comps, genexp_node.lineno, genexp_node.column) def handle_listcomp(self, listcomp_node): - elt, comps = self.comprehension_helper(listcomp_node, syms.list_for, - syms.list_if, syms.list_iter, - self.handle_testlist) + elt = self.handle_expr(listcomp_node.children[0]) + comps = self.comprehension_helper(listcomp_node.children[1], + "handle_testlist", + syms.list_for, syms.list_if, + syms.list_iter) return ast.ListComp(elt, comps, listcomp_node.lineno, listcomp_node.column) + def handle_setcomp(self, set_maker): + elt = self.handle_expr(set_maker.children[0]) + comps = self.comprehension_helper(set_maker.children[1]) + return ast.SetComp(elt, comps, set_maker.lineno, set_maker.column) + + def handle_dictcomp(self, dict_maker): + key = self.handle_expr(dict_maker.children[0]) + value = self.handle_expr(dict_maker.children[2]) + comps = self.comprehension_helper(dict_maker.children[3]) + return ast.DictComp(key, value, comps, dict_maker.lineno, + dict_maker.column) + def handle_exprlist(self, exprlist, context): exprs = [] for i in range(0, len(exprlist.children), 2): Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/asthelpers.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/asthelpers.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/asthelpers.py Thu Jun 24 02:27:03 2010 @@ -113,7 +113,17 @@ _description = "list comprehension" -class __extend__(ast.Dict, ast.Str, ast.Num, ast.Const): +class __extend__(ast.SetComp): + + _description = "set comprehension" + + +class __extend__(ast.DictComp): + + _description = "dict comprehension" + + +class __extend__(ast.Dict, ast.Set, ast.Str, ast.Num, ast.Const): _description = "literal" Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Thu Jun 24 02:27:03 2010 @@ -110,6 +110,47 @@ }) +class __extend__(ast.GeneratorExp): + + def build_container(self, codegen): + pass + + def get_generators(self): + return self.generators + + def accept_comp_iteration(self, codegen, index): + self.elt.walkabout(codegen) + codegen.emit_op(ops.YIELD_VALUE) + codegen.emit_op(ops.POP_TOP) + + +class __extend__(ast.SetComp): + + def build_container(self, codegen): + codegen.emit_op_arg(ops.BUILD_SET, 0) + + def get_generators(self): + return self.generators + + def accept_comp_iteration(self, codegen, index): + self.elt.walkabout(codegen) + codegen.emit_op_arg(ops.SET_ADD, index) + + +class __extend__(ast.DictComp): + + def build_container(self, codegen): + codegen.emit_op_arg(ops.BUILD_MAP, 0) + + def get_generators(self): + return self.generators + + def accept_comp_iteration(self, codegen, index): + self.value.walkabout(codegen) + self.key.walkabout(codegen) + codegen.emit_op_arg(ops.MAP_ADD, index) + + # These are frame blocks. F_BLOCK_LOOP = 0 F_BLOCK_EXCEPT = 1 @@ -1015,16 +1056,13 @@ self.emit_op_arg(ops.BUILD_LIST, 0) self._listcomp_generator(lc.generators, 0, lc.elt) - def _genexp_generator(self, generators, gen_index, elt): + def _comp_generator(self, node, generators, gen_index): start = self.new_block() skip = self.new_block() if_cleanup = self.new_block() anchor = self.new_block() - end = self.new_block() gen = generators[gen_index] assert isinstance(gen, ast.comprehension) - self.emit_jump(ops.SETUP_LOOP, end) - self.push_frame_block(F_BLOCK_LOOP, start) if gen_index == 0: self.argcount = 1 self.emit_op_arg(ops.LOAD_FAST, 0) @@ -1044,30 +1082,34 @@ ifs_count = 0 gen_index += 1 if gen_index < len(generators): - self._genexp_generator(generators, gen_index, elt) + self._comp_generator(node, generators, gen_index) else: - elt.walkabout(self) - self.emit_op(ops.YIELD_VALUE) - self.emit_op(ops.POP_TOP) - self.use_next_block(skip) + node.accept_comp_iteration(self, gen_index) self.use_next_block(if_cleanup) self.emit_jump(ops.JUMP_ABSOLUTE, start, True) self.use_next_block(anchor) - self.emit_op(ops.POP_BLOCK) - self.pop_frame_block(F_BLOCK_LOOP, start) - self.use_next_block(end) - def visit_GeneratorExp(self, genexp): - code = self.sub_scope(GenExpCodeGenerator, "", genexp, - genexp.lineno) - self.update_position(genexp.lineno) + def _compile_comprehension(self, node, name, sub_scope): + code = self.sub_scope(sub_scope, name, node, node.lineno) + self.update_position(node.lineno) self._make_function(code) - first_comp = genexp.generators[0] + first_comp = node.get_generators()[0] assert isinstance(first_comp, ast.comprehension) first_comp.iter.walkabout(self) self.emit_op(ops.GET_ITER) self.emit_op_arg(ops.CALL_FUNCTION, 1) + def visit_GeneratorExp(self, genexp): + self._compile_comprehension(genexp, "", GenExpCodeGenerator) + + def visit_SetComp(self, setcomp): + self._compile_comprehension(setcomp, "", + ComprehensionCodeGenerator) + + def visit_DictComp(self, dictcomp): + self._compile_comprehension(dictcomp, "", + ComprehensionCodeGenerator) + def visit_Repr(self, rep): self.update_position(rep.lineno) rep.value.walkabout(self) @@ -1259,15 +1301,25 @@ self.emit_op(ops.RETURN_VALUE) -class GenExpCodeGenerator(AbstractFunctionCodeGenerator): +class ComprehensionCodeGenerator(AbstractFunctionCodeGenerator): + + def _compile(self, node): + self.update_position(node.lineno) + node.build_container(self) + self._comp_generator(node, node.get_generators(), 0) + self._end_comp() + + def _end_comp(self): + self.emit_op(ops.RETURN_VALUE) + + +class GenExpCodeGenerator(ComprehensionCodeGenerator): - def _compile(self, genexp): - assert isinstance(genexp, ast.GeneratorExp) - self.update_position(genexp.lineno) - self._genexp_generator(genexp.generators, 0, genexp.elt) + def _end_comp(self): + pass def _get_code_flags(self): - flags = AbstractFunctionCodeGenerator._get_code_flags(self) + flags = ComprehensionCodeGenerator._get_code_flags(self) return flags | consts.CO_GENERATOR Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Thu Jun 24 02:27:03 2010 @@ -430,20 +430,31 @@ lamb.body.walkabout(self) self.pop_scope() - def visit_GeneratorExp(self, genexp): - outer = genexp.generators[0] + def _visit_comprehension(self, node, comps, *consider): + outer = comps[0] assert isinstance(outer, ast.comprehension) outer.iter.walkabout(self) - new_scope = FunctionScope("genexp", genexp.lineno, genexp.col_offset) - self.push_scope(new_scope, genexp) + new_scope = FunctionScope("genexp", node.lineno, node.col_offset) + self.push_scope(new_scope, node) self.implicit_arg(0) outer.target.walkabout(self) if outer.ifs: self.visit_sequence(outer.ifs) - self.visit_sequence(genexp.generators[1:]) - genexp.elt.walkabout(self) + self.visit_sequence(comps[1:]) + for item in consider: + item.walkabout(self) self.pop_scope() + def visit_GeneratorExp(self, genexp): + self._visit_comprehension(genexp, genexp.generators, genexp.elt) + + def visit_SetComp(self, setcomp): + self._visit_comprehension(setcomp, setcomp.generators, setcomp.elt) + + def visit_DictComp(self, dictcomp): + self._visit_comprehension(dictcomp, dictcomp.generators, + dictcomp.value, dictcomp.key) + def visit_With(self, wih): self.scope.new_temporary_name() if wih.optional_vars: Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Thu Jun 24 02:27:03 2010 @@ -718,6 +718,19 @@ assert v1.ctx == ast.Load assert isinstance(v2, ast.Num) + def test_set(self): + s = self.get_first_expr("{1}") + assert isinstance(s, ast.Set) + assert len(s.elts) == 1 + assert isinstance(s.elts[0], ast.Num) + assert self.space.eq_w(s.elts[0].n, self.space.wrap(1)) + s = self.get_first_expr("{0, 1, 2, 3, 4, 5}") + assert isinstance(s, ast.Set) + assert len(s.elts) == 6 + for i, elt in enumerate(s.elts): + assert isinstance(elt, ast.Num) + assert self.space.eq_w(elt.n, self.space.wrap(i)) + def test_set_context(self): tup = self.get_ast("(a, b) = c").body[0].targets[0] assert all(elt.ctx == ast.Store for elt in tup.elts) @@ -735,10 +748,13 @@ ("(x for y in g)", "generator expression"), ("(yield x)", "yield expression"), ("[x for y in g]", "list comprehension"), + ("{x for x in z}", "set comprehension"), + ("{x : x for x in z}", "dict comprehension"), ("'str'", "literal"), ("()", "()"), ("23", "literal"), ("{}", "literal"), + ("{1, 2, 3}", "literal"), ("(x > 4)", "comparison"), ("(x if y else a)", "conditional expression"), ("`x`", "repr") @@ -1161,3 +1177,45 @@ def test_listcomp(self): self.check_comprehension("[%s]", ast.ListComp) + + def test_setcomp(self): + self.check_comprehension("{%s}", ast.SetComp) + + def test_dictcomp(self): + gen = self.get_first_expr("{x : z for x in y}") + assert isinstance(gen, ast.DictComp) + assert isinstance(gen.key, ast.Name) + assert gen.key.ctx == ast.Load + assert isinstance(gen.value, ast.Name) + assert gen.value.ctx == ast.Load + assert len(gen.generators) == 1 + comp = gen.generators[0] + assert isinstance(comp, ast.comprehension) + assert comp.ifs is None + assert isinstance(comp.target, ast.Name) + assert isinstance(comp.iter, ast.Name) + assert comp.target.ctx == ast.Store + gen = self.get_first_expr("{x : z for x in y if w}") + comp = gen.generators[0] + assert len(comp.ifs) == 1 + test = comp.ifs[0] + assert isinstance(test, ast.Name) + gen = self.get_first_expr("{x : z for x, in y if w}") + tup = gen.generators[0].target + assert isinstance(tup, ast.Tuple) + assert len(tup.elts) == 1 + assert tup.ctx == ast.Store + gen = self.get_first_expr("{a : b for w in x for m in p if g}") + gens = gen.generators + assert len(gens) == 2 + comp1, comp2 = gens + assert comp1.ifs is None + assert len(comp2.ifs) == 1 + assert isinstance(comp2.ifs[0], ast.Name) + gen = self.get_first_expr("{x : z for x in y if m if g}") + comps = gen.generators + assert len(comps) == 1 + assert len(comps[0].ifs) == 2 + if1, if2 = comps[0].ifs + assert isinstance(if1, ast.Name) + assert isinstance(if2, ast.Name) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Thu Jun 24 02:27:03 2010 @@ -75,20 +75,39 @@ assert scp.lookup("x") == symtable.SCOPE_LOCAL self.check_unknown(scp, "y") - def test_genexp(self): - scp, gscp = self.gen_scope("(y[1] for y in z)") + def check_comprehension(self, template): + def brack(s): + return template % (s,) + scp, gscp = self.gen_scope(brack("y[1] for y in z")) assert scp.lookup("z") == symtable.SCOPE_GLOBAL_IMPLICIT self.check_unknown(scp, "y", "x") self.check_unknown(gscp, "z") assert gscp.lookup("y") == symtable.SCOPE_LOCAL assert gscp.lookup(".0") == symtable.SCOPE_LOCAL - scp, gscp = self.gen_scope("(x for x in z if x)") + scp, gscp = self.gen_scope(brack("x for x in z if x")) self.check_unknown(scp, "x") assert gscp.lookup("x") == symtable.SCOPE_LOCAL - scp, gscp = self.gen_scope("(x for y in g for f in n if f[h])") + scp, gscp = self.gen_scope(brack("x for y in g for f in n if f[h]")) self.check_unknown(scp, "f") assert gscp.lookup("f") == symtable.SCOPE_LOCAL + def test_genexp(self): + self.check_comprehension("(%s)") + + def test_setcomp(self): + self.check_comprehension("{%s}") + + def test_dictcomp(self): + scp, gscp = self.gen_scope("{x : x[3] for x in y}") + assert scp.lookup("y") == symtable.SCOPE_GLOBAL_IMPLICIT + self.check_unknown(scp, "a", "b", "x") + self.check_unknown(gscp, "y") + assert gscp.lookup("x") == symtable.SCOPE_LOCAL + assert gscp.lookup(".0") == symtable.SCOPE_LOCAL + scp, gscp = self.gen_scope("{x : x[1] for x in y if x[23]}") + self.check_unknown(scp, "x") + assert gscp.lookup("x") == symtable.SCOPE_LOCAL + def test_arguments(self): scp = self.func_scope("def f(): pass") assert not scp.children Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/tools/Python.asdl Thu Jun 24 02:27:03 2010 @@ -56,7 +56,10 @@ | Lambda(arguments args, expr body) | IfExp(expr test, expr body, expr orelse) | Dict(expr* keys, expr* values) + | Set(expr* elts) | ListComp(expr elt, comprehension* generators) + | SetComp(expr elt, comprehension* generators) + | DictComp(expr key, expr value, comprehension* generators) | GeneratorExp(expr elt, comprehension* generators) -- the grammar constrains where yield expressions can occur | Yield(expr? value) Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Thu Jun 24 02:27:03 2010 @@ -1002,6 +1002,17 @@ v = self.peekvalue(oparg) self.space.call_method(v, 'append', w) + def SET_ADD(self, oparg, next_instr): + w_value = self.popvalue() + w_set = self.peekvalue(oparg) + self.space.call_method(w_set, 'add', w_value) + + def MAP_ADD(self, oparg, next_instr): + w_key = self.popvalue() + w_value = self.popvalue() + w_dict = self.peekvalue(oparg) + self.space.setitem(w_dict, w_key, w_value) + def SET_LINENO(self, lineno, next_instr): pass @@ -1049,6 +1060,10 @@ w_dict = self.space.newdict() self.pushvalue(w_dict) + def BUILD_SET(self, itemcount, next_instr): + w_set = self.space.call_function(self.space.w_set) + self.pushvalue(w_set) + def STORE_MAP(self, zero, next_instr): raise BytecodeCorruption Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Thu Jun 24 02:27:03 2010 @@ -100,13 +100,13 @@ term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] -atom: ('(' [yield_expr|testlist_gexp] ')' | +atom: ('(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']' | - '{' [dictmaker] '}' | + '{' [dictorsetmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+) listmaker: test ( list_for | (',' test)* [','] ) -testlist_gexp: test ( gen_for | (',' test)* [','] ) +testlist_comp: test ( comp_for | (',' test)* [','] ) lambdef: 'lambda' [varargslist] ':' test trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] @@ -115,19 +115,21 @@ exprlist: expr (',' expr)* [','] testlist: test (',' test)* [','] dictmaker: test ':' test (',' test ':' test)* [','] +dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | + (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [testlist] ')'] ':' suite arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) -argument: test [gen_for] | test '=' test # Really [keyword '='] test +argument: test [comp_for] | test '=' test # Really [keyword '='] test list_iter: list_for | list_if list_for: 'for' exprlist 'in' testlist_safe [list_iter] list_if: 'if' old_test [list_iter] -gen_iter: gen_for | gen_if -gen_for: 'for' exprlist 'in' or_test [gen_iter] -gen_if: 'if' old_test [gen_iter] +comp_iter: comp_for | comp_if +comp_for: 'for' exprlist 'in' or_test [comp_iter] +comp_if: 'if' old_test [comp_iter] testlist1: test (',' test)* Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Thu Jun 24 02:27:03 2010 @@ -367,6 +367,24 @@ assert isinstance(ns["c"], str) +class AppTestComprehensions: + + def test_dictcomps(self): + d = eval("{x : x for x in range(10)}") + assert isinstance(d, dict) + assert d == dict(zip(range(10), range(10))) + d = eval("{x : x for x in range(10) if x % 2}") + l = [x for x in range(10) if x % 2] + assert d == dict(zip(l, l)) + + def test_setcomps(self): + s = eval("{x for x in range(10)}") + assert isinstance(s, set) + assert s == set(range(10)) + s = eval("{x for x in range(10) if x % 2}") + assert s == set(x for x in range(10) if x % 2) + + class AppTestWith: def test_with_simple(self): @@ -394,11 +412,11 @@ s = """class Context: def __init__(self, var): self.record = [] - self.var = a + self.var = var def __enter__(self): self.record.append(("__enter__", self.var)) return self.var - def __exit__(self): + def __exit__(self, tp, value, tb): self.record.append(("__exit__", self.var)) c1 = Context("blah") c2 = Context("bling") @@ -410,7 +428,7 @@ assert ns["v1"] == "blah" assert ns["v2"] == "bling" assert ns["c1"].record == [("__enter__", "blah"), ("__exit__", "blah")] - assert ns["c2"].record == [("__exit___", "bling"), + assert ns["c2"].record == [("__enter__", "bling"), ("__exit__", "bling")] From fijal at codespeak.net Thu Jun 24 02:33:51 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jun 2010 02:33:51 +0200 (CEST) Subject: [pypy-svn] r75549 - pypy/trunk/pypy/module/sys Message-ID: <20100624003351.68CB3282BAD@codespeak.net> Author: fijal Date: Thu Jun 24 02:33:49 2010 New Revision: 75549 Modified: pypy/trunk/pypy/module/sys/__init__.py pypy/trunk/pypy/module/sys/interp_encoding.py Log: An attempt to move calling of getfilesystemencoding a bit after (lazily is good) otherwise it might be too early, before sys.path is ready (patched in app_main) Modified: pypy/trunk/pypy/module/sys/__init__.py ============================================================================== --- pypy/trunk/pypy/module/sys/__init__.py (original) +++ pypy/trunk/pypy/module/sys/__init__.py Thu Jun 24 02:33:49 2010 @@ -96,11 +96,8 @@ if space.config.translating and not we_are_translated(): # don't get the filesystemencoding at translation time assert self.filesystemencoding is None - else: - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) - def getmodule(self, name): + def getmodule(self, name): space = self.space w_modules = self.get('modules') try: Modified: pypy/trunk/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/trunk/pypy/module/sys/interp_encoding.py (original) +++ pypy/trunk/pypy/module/sys/interp_encoding.py Thu Jun 24 02:33:49 2010 @@ -55,4 +55,6 @@ """Return the encoding used to convert Unicode filenames in operating system filenames. """ + if space.sys.filesystemencoding is None: + space.sys.filesystemencoding = _getfilesystemencoding(space) return space.wrap(space.sys.filesystemencoding) From benjamin at codespeak.net Thu Jun 24 04:55:32 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 24 Jun 2010 04:55:32 +0200 (CEST) Subject: [pypy-svn] r75550 - pypy/branch/fast-forward/lib-python Message-ID: <20100624025532.9698E282BAD@codespeak.net> Author: benjamin Date: Thu Jun 24 04:55:31 2010 New Revision: 75550 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: ignore platform:ERROR things Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Thu Jun 24 04:55:31 2010 @@ -7,6 +7,7 @@ import py import sys import pypy +import re from pypy.interpreter.gateway import ApplevelClass from pypy.interpreter.error import OperationError from pypy.interpreter.module import Module as PyPyModule @@ -747,7 +748,7 @@ outcome = 'ERROUT' test_stderr += ("-" * 80 + "\n") + out else: - if 'FAIL' in test_stdout or 'ERROR' in test_stderr: + if 'FAIL' in test_stdout or re.search('[^:]ERROR', test_stderr): outcome = 'FAIL' exit_status = 2 elif timedout: From fijal at codespeak.net Thu Jun 24 06:16:22 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jun 2010 06:16:22 +0200 (CEST) Subject: [pypy-svn] r75551 - in pypy/release/1.3.x: . pypy/module/cpyext pypy/module/sys pypy/tool/release pypy/tool/release/test Message-ID: <20100624041622.9210236C394@codespeak.net> Author: fijal Date: Thu Jun 24 06:16:17 2010 New Revision: 75551 Modified: pypy/release/1.3.x/ (props changed) pypy/release/1.3.x/pypy/module/cpyext/api.py pypy/release/1.3.x/pypy/module/sys/__init__.py pypy/release/1.3.x/pypy/module/sys/interp_encoding.py pypy/release/1.3.x/pypy/tool/release/package.py (props changed) pypy/release/1.3.x/pypy/tool/release/test/test_package.py (props changed) Log: Merge 75549 and 75547 from trunk Modified: pypy/release/1.3.x/pypy/module/cpyext/api.py ============================================================================== --- pypy/release/1.3.x/pypy/module/cpyext/api.py (original) +++ pypy/release/1.3.x/pypy/module/cpyext/api.py Thu Jun 24 06:16:17 2010 @@ -808,7 +808,6 @@ kwds["includes"] = ['Python.h'] # this is our Python.h # Generate definitions for global structures - struct_file = udir.join('pypy_structs.c') structs = ["#include "] for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): @@ -818,7 +817,7 @@ structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) elif typ == 'PyDateTime_CAPI*': structs.append('%s %s = NULL;' % (typ, name)) - struct_file.write('\n'.join(structs)) + struct_source = '\n'.join(structs) eci = ExternalCompilationInfo( include_dirs=include_dirs, @@ -832,9 +831,8 @@ source_dir / "bufferobject.c", source_dir / "object.c", source_dir / "cobject.c", - struct_file, ], - separate_module_sources = [code], + separate_module_sources = [code, struct_source], export_symbols=export_symbols_eci, compile_extra=compile_extra, **kwds Modified: pypy/release/1.3.x/pypy/module/sys/__init__.py ============================================================================== --- pypy/release/1.3.x/pypy/module/sys/__init__.py (original) +++ pypy/release/1.3.x/pypy/module/sys/__init__.py Thu Jun 24 06:16:17 2010 @@ -96,11 +96,8 @@ if space.config.translating and not we_are_translated(): # don't get the filesystemencoding at translation time assert self.filesystemencoding is None - else: - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) - def getmodule(self, name): + def getmodule(self, name): space = self.space w_modules = self.get('modules') try: Modified: pypy/release/1.3.x/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/release/1.3.x/pypy/module/sys/interp_encoding.py (original) +++ pypy/release/1.3.x/pypy/module/sys/interp_encoding.py Thu Jun 24 06:16:17 2010 @@ -55,4 +55,6 @@ """Return the encoding used to convert Unicode filenames in operating system filenames. """ + if space.sys.filesystemencoding is None: + space.sys.filesystemencoding = _getfilesystemencoding(space) return space.wrap(space.sys.filesystemencoding) From antocuni at codespeak.net Thu Jun 24 11:57:36 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jun 2010 11:57:36 +0200 (CEST) Subject: [pypy-svn] r75553 - in pypy/branch/sys-prefix/lib_pypy: . pypy_test Message-ID: <20100624095736.372EA282B9C@codespeak.net> Author: antocuni Date: Thu Jun 24 11:57:34 2010 New Revision: 75553 Modified: pypy/branch/sys-prefix/lib_pypy/dbm.py (contents, props changed) pypy/branch/sys-prefix/lib_pypy/pypy_test/test_dbm_extra.py Log: merge from trunk r75210 | afa | 2010-06-08 18:51:44 +0200 (Tue, 08 Jun 2010) | 3 lines Changed paths: M /pypy/trunk/pypy/lib/dbm.py A /pypy/trunk/pypy/lib/test2/test_dbm_extra.py issue467 resolved: add checks to the dbm module, avoids some segfaults Modified: pypy/branch/sys-prefix/lib_pypy/dbm.py ============================================================================== --- pypy/branch/sys-prefix/lib_pypy/dbm.py (original) +++ pypy/branch/sys-prefix/lib_pypy/dbm.py Thu Jun 24 11:57:34 2010 @@ -1,4 +1,4 @@ -from ctypes import * +from ctypes import Structure, c_char_p, c_int, c_void_p, CDLL import ctypes.util import os, sys @@ -15,6 +15,11 @@ ('dsize', c_int), ] + def __init__(self, text): + if not isinstance(text, str): + raise TypeError("datum: expected string, not %s" % type(text)) + Structure.__init__(self, text, len(text)) + class dbm(object): def __init__(self, dbmobj): self._aobj = dbmobj @@ -42,9 +47,7 @@ def get(self, key, default=None): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] @@ -65,12 +68,8 @@ def __setitem__(self, key, value): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) - data = datum() - data.dptr = c_char_p(value) - data.dsize = c_int(len(value)) + dat = datum(key) + data = datum(value) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_REPLACE) if getattr(lib, funcs['error'])(self._aobj): getattr(lib, funcs['clearerr'])(self._aobj) @@ -80,15 +79,11 @@ def setdefault(self, key, default=''): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return k.dptr[:k.dsize] - data = datum() - data.dptr = c_char_p(default) - data.dsize = c_int(len(default)) + data = datum(default) status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_INSERT) if status < 0: getattr(lib, funcs['clearerr'])(self._aobj) @@ -98,9 +93,7 @@ def has_key(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) k = getattr(lib, funcs['fetch'])(self._aobj, dat) if k.dptr: return True @@ -109,9 +102,7 @@ def __delitem__(self, key): if not self._aobj: raise error('DBM object has already been closed') - dat = datum() - dat.dptr = c_char_p(key) - dat.dsize = c_int(len(key)) + dat = datum(key) status = getattr(lib, funcs['delete'])(self._aobj, dat) if status < 0: raise KeyError(key) @@ -146,7 +137,7 @@ library = "GNU gdbm" funcs = {} -_init_func('open', [c_char_p, c_int, c_int]) +_init_func('open', (c_char_p, c_int, c_int)) _init_func('close', restype=c_void_p) _init_func('firstkey', restype=datum) _init_func('nextkey', restype=datum) @@ -160,6 +151,9 @@ def open(filename, flag='r', mode=0666): "open a DBM database" + if not isinstance(filename, str): + raise TypeError("expected string") + openflag = 0 try: @@ -177,3 +171,6 @@ if a_db == 0: raise error("Could not open file %s.db" % filename) return dbm(a_db) + +__all__ = ('datum', 'dbm', 'error', 'funcs', 'open', 'library') + Modified: pypy/branch/sys-prefix/lib_pypy/pypy_test/test_dbm_extra.py ============================================================================== --- pypy/branch/sys-prefix/lib_pypy/pypy_test/test_dbm_extra.py (original) +++ pypy/branch/sys-prefix/lib_pypy/pypy_test/test_dbm_extra.py Thu Jun 24 11:57:34 2010 @@ -44,3 +44,7 @@ d['xyz'] = '546' assert dict(d) == {'xyz': '546'} assert d['xyz'] == '546' + +def test_extra(): + py.test.raises(TypeError, dbm.datum, 123) + py.test.raises(TypeError, dbm.datum, False) From antocuni at codespeak.net Thu Jun 24 12:05:33 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jun 2010 12:05:33 +0200 (CEST) Subject: [pypy-svn] r75554 - in pypy/branch/sys-prefix: lib_pypy lib_pypy/pypy_test pypy/module/test_lib_pypy/ctypes_tests Message-ID: <20100624100533.698AE36C536@codespeak.net> Author: antocuni Date: Thu Jun 24 12:05:31 2010 New Revision: 75554 Modified: pypy/branch/sys-prefix/lib_pypy/ (props changed) pypy/branch/sys-prefix/lib_pypy/datetime.py pypy/branch/sys-prefix/lib_pypy/dbm.py (props changed) pypy/branch/sys-prefix/lib_pypy/pypy_test/test_functools.py (contents, props changed) pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/ (props changed) pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_unicode.py Log: merge from trunk ------------------------------------------------------------------------ r75334 | arigo | 2010-06-12 18:58:43 +0200 (Sat, 12 Jun 2010) | 5 lines Changed paths: M /pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py M /pypy/trunk/pypy/lib/app_test/ctypes_tests/test_unicode.py M /pypy/trunk/pypy/lib/app_test/test_functools.py Fix duplicate function names, i.e. places where we had two tests called 'test_'. Found using PyFlakes (thanks exarkun for the pointer). ------------------------------------------------------------------------ r75366 | arigo | 2010-06-13 11:18:12 +0200 (Sun, 13 Jun 2010) | 2 lines Changed paths: M /pypy/trunk/pypy/lib/app_test/ctypes_tests/test_functions.py Unsure. I think it's fine to get ArgumentError here. ------------------------------------------------------------------------ r75478 | arigo | 2010-06-20 11:27:42 +0200 (Sun, 20 Jun 2010) | 2 lines Changed paths: M /pypy/trunk/pypy/lib/datetime.py Typo (thanks Ademan). Modified: pypy/branch/sys-prefix/lib_pypy/datetime.py ============================================================================== --- pypy/branch/sys-prefix/lib_pypy/datetime.py (original) +++ pypy/branch/sys-prefix/lib_pypy/datetime.py Thu Jun 24 12:05:31 2010 @@ -1524,7 +1524,7 @@ # Convert self to UTC, and attach the new time zone object. myoffset = self.utcoffset() if myoffset is None: - raise ValuError("astimezone() requires an aware datetime") + raise ValueError("astimezone() requires an aware datetime") utc = (self - myoffset).replace(tzinfo=tz) # Convert from UTC to tz's local time. Modified: pypy/branch/sys-prefix/lib_pypy/pypy_test/test_functools.py ============================================================================== --- pypy/branch/sys-prefix/lib_pypy/pypy_test/test_functools.py (original) +++ pypy/branch/sys-prefix/lib_pypy/pypy_test/test_functools.py Thu Jun 24 12:05:31 2010 @@ -32,7 +32,7 @@ p = self.thetype(map, lambda x: x*10) assert p([1,2,3,4]) == [10, 20, 30, 40] - def test_attributes(self): + def test_attributes_1(self): p = self.thetype(capture, 1, 2, a=10, b=20) # attributes should be readable assert p.func == capture @@ -119,7 +119,7 @@ py.test.raises(ZeroDivisionError, self.thetype(f), 1, 0) py.test.raises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): + def test_attributes_2(self): p = self.thetype(hex) try: del p.__dict__ Modified: pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py (original) +++ pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py Thu Jun 24 12:05:31 2010 @@ -210,14 +210,14 @@ result = f(byref(c_int(99))) assert not result.contents == 99 - def test_errors(self): + def test_errors_1(self): f = dll._testfunc_p_p f.restype = c_int class X(Structure): _fields_ = [("y", c_int)] - raises(TypeError, f, X()) #cannot convert parameter + raises(ArgumentError, f, X()) #cannot convert parameter ################################################################ def test_shorts(self): @@ -305,7 +305,7 @@ assert 13577625587 == f(1000000000000, cb) - def test_errors(self): + def test_errors_2(self): raises(AttributeError, getattr, dll, "_xxx_yyy") raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") Modified: pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_unicode.py ============================================================================== --- pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_unicode.py (original) +++ pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ctypes_tests/test_unicode.py Thu Jun 24 12:05:31 2010 @@ -90,7 +90,7 @@ assert func(u"abc") == "abc" assert func(u"????") == "" - def test_ascii_replace(self): + def test_ascii_replace_2(self): ctypes.set_conversion_mode("ascii", "replace") assert func("abc") == "abc" assert func(u"abc") == "abc" From antocuni at codespeak.net Thu Jun 24 12:07:55 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jun 2010 12:07:55 +0200 (CEST) Subject: [pypy-svn] r75555 - in pypy/branch/sys-prefix/lib-python: . modified-2.5.2/distutils modified-2.5.2/distutils/command modified-2.5.2/distutils/tests Message-ID: <20100624100755.D464D282B9C@codespeak.net> Author: antocuni Date: Thu Jun 24 12:07:54 2010 New Revision: 75555 Added: pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py - copied unchanged from r75554, pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py Modified: pypy/branch/sys-prefix/lib-python/ (props changed) pypy/branch/sys-prefix/lib-python/conftest.py pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/msvccompiler.py pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Log: merge from trunk -r74817:HEAD ------------------------------------------------------------------------ r75092 | hpk | 2010-06-04 01:18:53 +0200 (Fri, 04 Jun 2010) | 2 lines fix collection of lib-python tests under py.py ------------------------------------------------------------------------ r75098 | arigo | 2010-06-04 11:13:54 +0200 (Fri, 04 Jun 2010) | 5 lines Revert r75092. It causes massive failures of the nightly applevel tests. I think (by running pypy-c py.test --collect) that it is because in this case it causes py.test to try to collect far more stuff, including both the 2.5.2/test and the modified-2.5.2/test version of the same test. ------------------------------------------------------------------------ r75113 | hpk | 2010-06-04 17:45:17 +0200 (Fri, 04 Jun 2010) | 14 lines try to redo the fix related to testing in lib-python. Tests are now collected more "normally" in their respective directories 2.5.2/test and modified-2.5.2/test instead of "faking" an artifical tree at lib-python level. Note that you will get a collection error if you run a specific test via "py.ttest lib-python/2.5.2/test/test_XYZ.py" if there is a test_XYZ in the modified-2.5.2 directory. Running "py.test lib-python" or "py.test --pypy=pypy-c lib-python" will run both modified and unmodified tests as is to be expected and filenames during testing progress clearly indicate where a test comes from. ------------------------------------------------------------------------ r75195 | afa | 2010-06-08 16:04:01 +0200 (Tue, 08 Jun 2010) | 2 lines Revert part of the change, and use the same name as CPython for the import library ------------------------------------------------------------------------ r75196 | afa | 2010-06-08 16:31:42 +0200 (Tue, 08 Jun 2010) | 5 lines On Windows, correctly retrieve the version of the compiler used to compile the interpreter. Don't rely on sys.version (pypy does not indicates the compiler version), directly fetch the manifest embedded in the program. ------------------------------------------------------------------------ r75234 | arigo | 2010-06-09 12:16:02 +0200 (Wed, 09 Jun 2010) | 2 lines Attempt to skip this file on non-Windows platforms. ------------------------------------------------------------------------ r75476 | fijal | 2010-06-20 07:39:42 +0200 (Sun, 20 Jun 2010) | 2 lines Look also into pypy_prefix/include, hopefully a short living hack. ------------------------------------------------------------------------ Modified: pypy/branch/sys-prefix/lib-python/conftest.py ============================================================================== --- pypy/branch/sys-prefix/lib-python/conftest.py (original) +++ pypy/branch/sys-prefix/lib-python/conftest.py Thu Jun 24 12:07:54 2010 @@ -520,11 +520,14 @@ return cache.get(name, None) def collect(self): + we_are_in_modified = self.fspath == modregrtestdir l = [] - for x in testmap: + for x in self.fspath.listdir(): name = x.basename regrtest = self.get(name) - if regrtest is not None: + if regrtest is not None: + if bool(we_are_in_modified) ^ regrtest.ismodified(): + continue #if option.extracttests: # l.append(InterceptedRunModule(name, self, regrtest)) #else: @@ -532,7 +535,14 @@ return l def pytest_collect_directory(parent, path): - return RegrDirectory(path, parent) + # use RegrDirectory collector for both modified and unmodified tests + if path in (modregrtestdir, regrtestdir): + return RegrDirectory(path, parent) + +def pytest_ignore_collect(path): + # ignore all files - only RegrDirectory generates tests in lib-python + if path.check(file=1): + return True class RunFileExternal(py.test.collect.File): def __init__(self, name, parent, regrtest): Modified: pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/command/build_ext.py Thu Jun 24 12:07:54 2010 @@ -647,7 +647,9 @@ """ # The python library is always needed on Windows. if sys.platform == "win32": - pythonlib = 'libpypy-c.exe' + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] Modified: pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/msvccompiler.py ============================================================================== --- pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/msvccompiler.py (original) +++ pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/msvccompiler.py Thu Jun 24 12:07:54 2010 @@ -159,14 +159,60 @@ s = s.replace(k, v) return s +def get_manifests(): + """Retrieves the manifest(s) embedded in the current executable""" + import ctypes.wintypes + EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA + EnumResourceNameCallback = ctypes.WINFUNCTYPE( + ctypes.wintypes.BOOL, + ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, + ctypes.wintypes.LONG, ctypes.wintypes.LONG) + FindResource = ctypes.windll.kernel32.FindResourceA + LoadResource = ctypes.windll.kernel32.LoadResource + FreeResource = ctypes.windll.kernel32.FreeResource + SizeofResource = ctypes.windll.kernel32.SizeofResource + LockResource = ctypes.windll.kernel32.LockResource + UnlockResource = lambda x: None # hehe + + manifests = [] + + def callback(hModule, lpType, lpName, lParam): + hResource = FindResource(hModule, lpName, lpType) + size = SizeofResource(hModule, hResource) + hData = LoadResource(hModule, hResource) + try: + ptr = LockResource(hData) + try: + manifests.append(ctypes.string_at(ptr, size)) + finally: + UnlockResource(hData) + finally: + FreeResource(hData) + return True + + hModule = None # main executable + RT_MANIFEST = 24 # from WinUser.h + EnumResourceNames(hModule, RT_MANIFEST, + EnumResourceNameCallback(callback), None) + return manifests + def get_build_version(): """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. """ + try: + manifests = get_manifests() + for manifest in manifests: + match = re.search('"Microsoft.VC([0-9]+).CRT"', manifest) + if match: + return int(match.group(1)) / 10.0 + except BaseException: + pass + # No manifest embedded, use default compiler version return 9.0 +def get_build_architecture(): + return 'Intel' + def normalize_and_reduce_paths(paths): """Return a list of normalized paths with duplicates removed. Modified: pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/branch/sys-prefix/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Thu Jun 24 12:07:54 2010 @@ -13,6 +13,9 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j + cand = j(sys.pypy_prefix, 'include') + if os.path.exists(cand): + return cand if plat_specific: return j(sys.prefix, "pypy", "_interfaces") return j(sys.prefix, 'pypy', 'module', 'cpyext', 'include') From antocuni at codespeak.net Thu Jun 24 12:44:27 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jun 2010 12:44:27 +0200 (CEST) Subject: [pypy-svn] r75556 - in pypy/trunk: lib-python lib-python/modified-2.5.2 lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command lib-python/modified-2.5.2/test lib_pypy lib_pypy/_ctypes lib_pypy/ctypes_config_cache lib_pypy/ctypes_config_cache/test lib_pypy/distributed lib_pypy/distributed/demo lib_pypy/pypy_test lib_pypy/xml lib_pypy/xml/dom lib_pypy/xml/etree lib_pypy/xml/parsers lib_pypy/xml/sax pypy pypy/annotation pypy/annotation/test pypy/bin pypy/config pypy/doc pypy/doc/config pypy/interpreter pypy/interpreter/test pypy/jit/backend pypy/jit/backend/x86 pypy/jit/backend/x86/tool pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/module pypy/module/__builtin__/test pypy/module/_codecs/test pypy/module/_sre/test pypy/module/cpyext/test pypy/module/sys pypy/module/sys/test pypy/module/test_lib_pypy pypy/module/test_lib_pypy/ctypes_tests pypy/module/test_lib_pypy/test_distributed pypy/objspace/flow pypy/rlib pypy/rlib/parsing/test pypy/rlib/rsdl/test pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory pypy/rpython/microbench pypy/rpython/ootypesystem pypy/tool pypy/tool/algo pypy/tool/algo/test pypy/tool/pytest pypy/tool/release pypy/tool/release/test pypy/tool/test pypy/translator pypy/translator/benchmark pypy/translator/c pypy/translator/c/gcc pypy/translator/c/test pypy/translator/cli/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/microbench/pybench pypy/translator/oosupport pypy/translator/sandbox pypy/translator/sandbox/test pypy/translator/test pypy/translator/tool site-packages Message-ID: <20100624104427.95E73282B9C@codespeak.net> Author: antocuni Date: Thu Jun 24 12:44:22 2010 New Revision: 75556 Added: pypy/trunk/lib_pypy/ (props changed) - copied from r75555, pypy/branch/sys-prefix/lib_pypy/ pypy/trunk/pypy/module/conftest.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/module/conftest.py pypy/trunk/pypy/module/sys/test/test_initialpath.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/module/sys/test/test_initialpath.py pypy/trunk/pypy/module/test_lib_pypy/ (props changed) - copied from r75555, pypy/branch/sys-prefix/pypy/module/test_lib_pypy/ pypy/trunk/pypy/tool/identity_dict.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/tool/identity_dict.py pypy/trunk/pypy/tool/lib_pypy.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/tool/lib_pypy.py pypy/trunk/pypy/tool/test/test_identitydict.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/tool/test/test_identitydict.py pypy/trunk/pypy/tool/test/test_lib_pypy.py - copied unchanged from r75555, pypy/branch/sys-prefix/pypy/tool/test/test_lib_pypy.py pypy/trunk/site-packages/ - copied from r75555, pypy/branch/sys-prefix/site-packages/ Removed: pypy/trunk/pypy/jit/tl/run_all_tests.py Modified: pypy/trunk/lib-python/ (props changed) pypy/trunk/lib-python/conftest.py pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig.py pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/trunk/lib-python/modified-2.5.2/site.py pypy/trunk/lib-python/modified-2.5.2/test/regrtest.py pypy/trunk/lib-python/modified-2.5.2/test/test_doctest.py pypy/trunk/lib-python/modified-2.5.2/test/test_sys.py pypy/trunk/lib_pypy/_ctypes/ (props changed) pypy/trunk/lib_pypy/ctypes_config_cache/ (props changed) pypy/trunk/lib_pypy/ctypes_config_cache/test/ (props changed) pypy/trunk/lib_pypy/distributed/ (props changed) pypy/trunk/lib_pypy/distributed/demo/ (props changed) pypy/trunk/lib_pypy/pypy_test/ (props changed) pypy/trunk/lib_pypy/xml/ (props changed) pypy/trunk/lib_pypy/xml/dom/ (props changed) pypy/trunk/lib_pypy/xml/etree/ (props changed) pypy/trunk/lib_pypy/xml/parsers/ (props changed) pypy/trunk/lib_pypy/xml/sax/ (props changed) pypy/trunk/pypy/annotation/bookkeeper.py pypy/trunk/pypy/annotation/test/autopath.py pypy/trunk/pypy/bin/autopath.py pypy/trunk/pypy/bin/py.py pypy/trunk/pypy/config/autopath.py pypy/trunk/pypy/config/pypyoption.py pypy/trunk/pypy/conftest.py pypy/trunk/pypy/doc/_ref.txt pypy/trunk/pypy/doc/coding-guide.txt pypy/trunk/pypy/doc/config/autopath.py pypy/trunk/pypy/doc/config/objspace.usemodules.md5.txt pypy/trunk/pypy/doc/config/objspace.usemodules.sha.txt pypy/trunk/pypy/doc/config/objspace.usemodules.struct.txt pypy/trunk/pypy/doc/cpython_differences.txt pypy/trunk/pypy/doc/ctypes-implementation.txt pypy/trunk/pypy/doc/docindex.txt pypy/trunk/pypy/doc/getting-started-python.txt pypy/trunk/pypy/doc/maemo.txt pypy/trunk/pypy/doc/objspace-proxies.txt pypy/trunk/pypy/doc/sandbox.txt pypy/trunk/pypy/doc/stackless.txt pypy/trunk/pypy/interpreter/baseobjspace.py pypy/trunk/pypy/interpreter/test/test_module.py pypy/trunk/pypy/interpreter/test/test_objspace.py pypy/trunk/pypy/jit/backend/autopath.py pypy/trunk/pypy/jit/backend/x86/autopath.py pypy/trunk/pypy/jit/backend/x86/tool/autopath.py pypy/trunk/pypy/jit/tl/autopath.py pypy/trunk/pypy/jit/tl/spli/autopath.py pypy/trunk/pypy/jit/tool/autopath.py pypy/trunk/pypy/module/__builtin__/test/autopath.py pypy/trunk/pypy/module/_codecs/test/autopath.py pypy/trunk/pypy/module/_sre/test/autopath.py pypy/trunk/pypy/module/cpyext/test/test_cpyext.py pypy/trunk/pypy/module/sys/__init__.py pypy/trunk/pypy/module/sys/state.py pypy/trunk/pypy/module/sys/test/autopath.py pypy/trunk/pypy/module/sys/version.py pypy/trunk/pypy/module/test_lib_pypy/ctypes_tests/ (props changed) pypy/trunk/pypy/module/test_lib_pypy/test_distributed/ (props changed) pypy/trunk/pypy/objspace/flow/model.py pypy/trunk/pypy/pytest-A.cfg pypy/trunk/pypy/rlib/parsing/test/autopath.py pypy/trunk/pypy/rlib/rmd5.py pypy/trunk/pypy/rlib/rsdl/test/autopath.py pypy/trunk/pypy/rlib/rsha.py pypy/trunk/pypy/rlib/rzipfile.py pypy/trunk/pypy/rpython/lltypesystem/lltype.py pypy/trunk/pypy/rpython/lltypesystem/rclass.py pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py pypy/trunk/pypy/rpython/memory/gctypelayout.py pypy/trunk/pypy/rpython/microbench/autopath.py pypy/trunk/pypy/rpython/ootypesystem/rclass.py pypy/trunk/pypy/tool/algo/graphlib.py pypy/trunk/pypy/tool/algo/test/autopath.py pypy/trunk/pypy/tool/autopath.py pypy/trunk/pypy/tool/compat.py pypy/trunk/pypy/tool/pytest/autopath.py pypy/trunk/pypy/tool/pytest/confpath.py pypy/trunk/pypy/tool/release/package.py pypy/trunk/pypy/tool/release/test/test_package.py pypy/trunk/pypy/tool/stdlib___future__.py pypy/trunk/pypy/tool/stdlib_opcode.py pypy/trunk/pypy/tool/test/autopath.py pypy/trunk/pypy/translator/autopath.py pypy/trunk/pypy/translator/benchmark/autopath.py pypy/trunk/pypy/translator/c/autopath.py pypy/trunk/pypy/translator/c/database.py pypy/trunk/pypy/translator/c/funcgen.py pypy/trunk/pypy/translator/c/gcc/autopath.py pypy/trunk/pypy/translator/c/test/autopath.py pypy/trunk/pypy/translator/cli/test/autopath.py pypy/trunk/pypy/translator/geninterplevel.py pypy/trunk/pypy/translator/goal/app_main.py pypy/trunk/pypy/translator/goal/autopath.py pypy/trunk/pypy/translator/goal/targetpypystandalone.py pypy/trunk/pypy/translator/goal/test2/autopath.py pypy/trunk/pypy/translator/goal/test2/test_app_main.py pypy/trunk/pypy/translator/microbench/pybench/autopath.py pypy/trunk/pypy/translator/oosupport/function.py pypy/trunk/pypy/translator/sandbox/autopath.py pypy/trunk/pypy/translator/sandbox/pypy_interact.py pypy/trunk/pypy/translator/sandbox/sandlib.py pypy/trunk/pypy/translator/sandbox/test/autopath.py pypy/trunk/pypy/translator/sandbox/test/test_pypy_interact.py pypy/trunk/pypy/translator/test/autopath.py pypy/trunk/pypy/translator/tool/autopath.py pypy/trunk/pypy/translator/tool/lltracker.py Log: merge the sys-prefix branch. The most important changes are: 1) trunk/pypy/lib has been moved to trunk/lib_pypy: the code there is really pure python and should not depend on pypy. However, some of the tests existed as AppLevel tests: since they need to be run inside the pypy/ package, they have been moved to pypy/module/test_lib_pypy. Also, a custom conftest makes py.test module/test_lib_pypy also run the tests in ../lib_pypy 2) sys.pypy_prefix has been removed. Instead, sys.prefix and sys.exec_prefix (which are always the same) are added. The prefix is searched at runtime, starting from the directory where the pypy executable resides and walking up until it finds the expected directoris (lib-python and lib_pypy) The layout of the svn checkout has been designed in a way that it will be possibile to run virtualenv -p translator/goal/pypy-c, without needing to install pypy system-wide Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Thu Jun 24 12:44:22 2010 @@ -20,8 +20,8 @@ regrtestdir, modregrtestdir, testresultdir pytest_plugins = "resultlog", -rsyncdirs = ['.', '../pypy'] - +rsyncdirs = ['.', '../pypy/'] + # # Interfacing/Integrating with py.test's collection process # Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py Thu Jun 24 12:44:22 2010 @@ -18,7 +18,8 @@ # return a list of 'site' dirs for easy_install from pkg_resources import normalize_path sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep)) - sitedirs.append(os.path.join(sys.pypy_prefix, 'site-packages')) + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedirs.append(os.path.join(sys.prefix, 'lib', pypylib, 'site-packages')) sitedirs = map(normalize_path, sitedirs) return sitedirs Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py Thu Jun 24 12:44:22 2010 @@ -167,7 +167,7 @@ # for Release and Debug builds. # also Python's library directory must be appended to library_dirs if os.name == 'nt': - self.library_dirs.append(os.path.join(sys.pypy_prefix, 'pypy', '_interfaces')) + self.library_dirs.append(os.path.join(sys.prefix, 'pypy', '_interfaces')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py Thu Jun 24 12:44:22 2010 @@ -67,8 +67,8 @@ 'data' : '$base', }, 'pypy': { - 'purelib': '$base/site-packages', - 'platlib': '$base/site-packages', + 'purelib': '$base/lib/pypy$pypy_version_short/site-packages', + 'platlib': '$base/lib/pypy$pypy_version_short/site-packages', 'headers': '$base/include', 'scripts': '$base/bin', 'data' : '$base', @@ -283,6 +283,7 @@ 'dist_fullname': self.distribution.get_fullname(), 'py_version': py_version, 'py_version_short': py_version[0:3], + 'pypy_version_short': '%d.%d' % sys.pypy_version_info[:2], 'sys_prefix': prefix, 'prefix': prefix, 'sys_exec_prefix': exec_prefix, @@ -391,13 +392,9 @@ if self.exec_prefix is not None: raise DistutilsOptionError, \ "must not supply exec-prefix without prefix" - - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - self.exec_prefix = self.prefix - else: - self.prefix = os.path.normpath(sys.prefix) - self.exec_prefix = os.path.normpath(sys.exec_prefix) + + self.prefix = os.path.normpath(sys.prefix) + self.exec_prefix = os.path.normpath(sys.exec_prefix) else: if self.exec_prefix is None: @@ -417,10 +414,7 @@ self.select_scheme("unix_home") else: if self.prefix is None: - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - else: - self.prefix = os.path.normpath(sys.prefix) + self.prefix = os.path.normpath(sys.prefix) self.install_base = self.install_platbase = self.prefix try: @@ -434,7 +428,7 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! - if hasattr(sys, 'pypy_prefix'): + if hasattr(sys, 'pypy_version_info'): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig.py Thu Jun 24 12:44:22 2010 @@ -19,5 +19,7 @@ if '__pypy__' in sys.builtin_module_names: from distutils.sysconfig_pypy import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools else: from distutils.sysconfig_cpython import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Thu Jun 24 12:44:22 2010 @@ -7,7 +7,7 @@ from distutils.errors import DistutilsPlatformError -PYPY_PREFIX = os.path.normpath(sys.pypy_prefix) +PREFIX = os.path.normpath(sys.prefix) python_build = False @@ -17,8 +17,8 @@ if os.path.exists(cand): return cand if plat_specific: - return j(sys.pypy_prefix, "pypy", "_interfaces") - return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') + return j(sys.prefix, "pypy", "_interfaces") + return j(sys.prefix, 'pypy', 'module', 'cpyext', 'include') def get_python_version(): """Return a string containing the major and minor Python version, @@ -46,8 +46,9 @@ raise DistutilsPlatformError( "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: - prefix = PYPY_PREFIX - return os.path.join(prefix, "site-packages") + prefix = PREFIX + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + return os.path.join(prefix, 'lib', pypylib, 'site-packages') _config_vars = None Modified: pypy/trunk/lib-python/modified-2.5.2/site.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/site.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/site.py Thu Jun 24 12:44:22 2010 @@ -175,8 +175,9 @@ def addsitepackages(known_paths): """Add site-packages to sys.path, in a PyPy-specific way.""" - if hasattr(sys, 'pypy_prefix'): - sitedir = os.path.join(sys.pypy_prefix, "site-packages") + if hasattr(sys, 'pypy_version_info'): + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedir = os.path.join(sys.prefix, 'lib', pypylib, 'site-packages') if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) return None Modified: pypy/trunk/lib-python/modified-2.5.2/test/regrtest.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/regrtest.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/regrtest.py Thu Jun 24 12:44:22 2010 @@ -348,11 +348,8 @@ random.shuffle(tests) if trace: import trace - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=False, count=True) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], + trace=False, count=True) test_support.verbose = verbose # Tell tests to be moderately quiet test_support.use_resources = use_resources save_modules = sys.modules.keys() Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_doctest.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_doctest.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_doctest.py Thu Jun 24 12:44:22 2010 @@ -2422,11 +2422,8 @@ import trace, sys, re, StringIO def test_coverage(coverdir): - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=0, count=1) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,], + trace=0, count=1) tracer.run('reload(doctest); test_main()') r = tracer.results() print 'Writing coverage results...' Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_sys.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_sys.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_sys.py Thu Jun 24 12:44:22 2010 @@ -334,11 +334,8 @@ if test.test_support.have_unicode: self.assert_(isinstance(sys.maxunicode, int)) self.assert_(isinstance(sys.platform, basestring)) - if hasattr(sys, 'prefix'): - self.assert_(isinstance(sys.prefix, basestring)) - self.assert_(isinstance(sys.exec_prefix, basestring)) - else: - self.assert_(isinstance(sys.pypy_prefix, basestring)) # PyPy only + self.assert_(isinstance(sys.prefix, basestring)) + self.assert_(isinstance(sys.exec_prefix, basestring)) self.assert_(isinstance(sys.version, basestring)) vi = sys.version_info self.assert_(isinstance(vi, tuple)) Modified: pypy/trunk/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/pypy/annotation/bookkeeper.py Thu Jun 24 12:44:22 2010 @@ -22,7 +22,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython import extregistry -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class Stats: Modified: pypy/trunk/pypy/annotation/test/autopath.py ============================================================================== --- pypy/trunk/pypy/annotation/test/autopath.py (original) +++ pypy/trunk/pypy/annotation/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/bin/autopath.py ============================================================================== --- pypy/trunk/pypy/bin/autopath.py (original) +++ pypy/trunk/pypy/bin/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/bin/py.py ============================================================================== --- pypy/trunk/pypy/bin/py.py (original) +++ pypy/trunk/pypy/bin/py.py Thu Jun 24 12:44:22 2010 @@ -11,6 +11,7 @@ except ImportError: pass +import pypy from pypy.tool import option from optparse import make_option from pypy.interpreter import main, interactive, error, gateway @@ -84,6 +85,14 @@ space.setitem(space.sys.w_dict, space.wrap('executable'), space.wrap(argv[0])) + # call pypy_initial_path: the side-effect is that it sets sys.prefix and + # sys.exec_prefix + srcdir = os.path.dirname(os.path.dirname(pypy.__file__)) + space.appexec([space.wrap(srcdir)], """(srcdir): + import sys + sys.pypy_initial_path(srcdir) + """) + # set warning control options (if any) warn_arg = interactiveconfig.warn if warn_arg is not None: Modified: pypy/trunk/pypy/config/autopath.py ============================================================================== --- pypy/trunk/pypy/config/autopath.py (original) +++ pypy/trunk/pypy/config/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Thu Jun 24 12:44:22 2010 @@ -8,7 +8,8 @@ modulepath = py.path.local(__file__).dirpath().dirpath().join("module") all_modules = [p.basename for p in modulepath.listdir() if p.check(dir=True, dotfile=False) - and p.join('__init__.py').check()] + and p.join('__init__.py').check() + and not p.basename.startswith('test')] essential_modules = dict.fromkeys( ["exceptions", "_file", "sys", "__builtin__", "posix"] Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Thu Jun 24 12:44:22 2010 @@ -10,11 +10,9 @@ # pytest settings pytest_plugins = "resultlog", -rsyncdirs = ['.', '../lib-python', '../demo'] +rsyncdirs = ['.', '../lib-python', '../lib_pypy', '../demo'] rsyncignore = ['_cache'] -collect_ignore = ['./lib/py'] - # PyPy's command line extra options (these are added # to py.test's standard options) # @@ -220,8 +218,10 @@ def accept_regular_test(self): if option.runappdirect: - # only collect regular tests if we are in an 'app_test' directory - return "app_test" in self.listnames() + # only collect regular tests if we are in an 'app_test' directory, + # or in test_lib_pypy + names = self.listnames() + return "app_test" in names or "test_lib_pypy" in names else: return True @@ -232,7 +232,7 @@ return True return False - def classnamefilter(self, name): + def classnamefilter(self, name): if name.startswith('Test'): return self.accept_regular_test() if name.startswith('AppTest'): Modified: pypy/trunk/pypy/doc/_ref.txt ============================================================================== --- pypy/trunk/pypy/doc/_ref.txt (original) +++ pypy/trunk/pypy/doc/_ref.txt Thu Jun 24 12:44:22 2010 @@ -46,11 +46,10 @@ .. _`pypy/interpreter/astcompiler/ast.py`: ../../pypy/interpreter/astcompiler/ast.py .. _`pypy/interpreter/typedef.py`: ../../pypy/interpreter/typedef.py .. _`lib/`: -.. _`pypy/lib/`: ../../pypy/lib -.. _`lib/app_test/`: ../../pypy/lib/app_test -.. _`lib/distributed/`: ../../pypy/lib/distributed -.. _`pypy/lib/stackless.py`: ../../pypy/lib/stackless.py -.. _`pypy/lib/test2`: ../../pypy/lib/test2 +.. _`lib_pypy/`: ../../lib_pypy +.. _`lib/distributed/`: ../../lib_pypy/distributed +.. _`lib_pypy/stackless.py`: ../../lib_pypy/stackless.py +.. _`lib_pypy/pypy_test/`: ../../lib_pypy/pypy_test .. _`module/`: .. _`pypy/module`: .. _`pypy/module/`: ../../pypy/module Modified: pypy/trunk/pypy/doc/coding-guide.txt ============================================================================== --- pypy/trunk/pypy/doc/coding-guide.txt (original) +++ pypy/trunk/pypy/doc/coding-guide.txt Thu Jun 24 12:44:22 2010 @@ -631,7 +631,7 @@ because they rely on implementation details of CPython. If we don't just modify an original CPython module but need to rewrite -it from scratch we put it into `pypy/lib/`_ as a pure application level +it from scratch we put it into `lib_pypy/`_ as a pure application level module. When we need access to interpreter-level objects we put the module into @@ -653,7 +653,7 @@ >>>> import operator >>>> operator.__file__ - '/home/hpk/pypy-dist/pypy/lib/operator.py' + '/home/hpk/pypy-dist/lib_pypy/operator.py' >>>> import opcode >>>> opcode.__file__ @@ -682,7 +682,7 @@ list of directories, specified in the ``PYTHONPATH`` environment variable. -*pypy/lib/* +*lib_pypy/* contains pure Python reimplementation of modules. @@ -794,14 +794,14 @@ --withoutmod-mymodule (the later being the default)) for py.py and translate.py. -Testing modules in ``pypy/lib`` +Testing modules in ``lib_pypy/`` -------------------------------- -You can go to the `pypy/lib/test2`_ directory and invoke the testing tool -("py.test" or "python ../../test_all.py") to run tests against the -pypy/lib hierarchy. Note, that tests in `pypy/lib/test2`_ are allowed +You can go to the `lib_pypy/pypy_test/`_ directory and invoke the testing tool +("py.test" or "python ../../pypy/test_all.py") to run tests against the +lib_pypy hierarchy. Note, that tests in `lib_pypy/pypy_test/`_ are allowed and encouraged to let their tests run at interpreter level although -`pypy/lib/`_ modules eventually live at PyPy's application level. +`lib_pypy/`_ modules eventually live at PyPy's application level. This allows us to quickly test our python-coded reimplementations against CPython. Modified: pypy/trunk/pypy/doc/config/autopath.py ============================================================================== --- pypy/trunk/pypy/doc/config/autopath.py (original) +++ pypy/trunk/pypy/doc/config/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/doc/config/objspace.usemodules.md5.txt ============================================================================== --- pypy/trunk/pypy/doc/config/objspace.usemodules.md5.txt (original) +++ pypy/trunk/pypy/doc/config/objspace.usemodules.md5.txt Thu Jun 24 12:44:22 2010 @@ -1,5 +1,5 @@ Use the built-in 'md5' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/trunk/pypy/doc/config/objspace.usemodules.sha.txt ============================================================================== --- pypy/trunk/pypy/doc/config/objspace.usemodules.sha.txt (original) +++ pypy/trunk/pypy/doc/config/objspace.usemodules.sha.txt Thu Jun 24 12:44:22 2010 @@ -1,5 +1,5 @@ Use the built-in 'sha' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/trunk/pypy/doc/config/objspace.usemodules.struct.txt ============================================================================== --- pypy/trunk/pypy/doc/config/objspace.usemodules.struct.txt (original) +++ pypy/trunk/pypy/doc/config/objspace.usemodules.struct.txt Thu Jun 24 12:44:22 2010 @@ -1,5 +1,5 @@ Use the built-in 'struct' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/trunk/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/trunk/pypy/doc/cpython_differences.txt (original) +++ pypy/trunk/pypy/doc/cpython_differences.txt Thu Jun 24 12:44:22 2010 @@ -71,7 +71,7 @@ _stackless * Supported by being rewritten in pure Python (possibly using ``ctypes``): - see the `pypy/lib/`_ directory. Examples of modules that we + see the `lib_pypy/`_ directory. Examples of modules that we support this way: ``ctypes``, ``array``, ``cPickle``, ``cStringIO``, ``cmath``, ``dbm`` (?), ``datetime``, ``binascii``... Note that some modules are both in there and in the list above; @@ -79,7 +79,7 @@ at translation time). The extension modules (i.e. modules written in C, in the standard CPython) -that are neither mentioned above nor in `pypy/lib/`_ are not available in PyPy. +that are neither mentioned above nor in `lib_pypy/`_ are not available in PyPy. .. the nonstandard modules are listed below... .. _`__pypy__`: __pypy__-module.html Modified: pypy/trunk/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/trunk/pypy/doc/ctypes-implementation.txt (original) +++ pypy/trunk/pypy/doc/ctypes-implementation.txt Thu Jun 24 12:44:22 2010 @@ -48,9 +48,9 @@ High-level parts ================= -The reused ``ctypes`` package lives in ``pypy/lib/ctypes``. ``_ctypes`` +The reused ``ctypes`` package lives in ``lib_pypy/ctypes``. ``_ctypes`` implementing the same interface as ``_ctypes`` in CPython is in -``pypy/lib/_ctypes``. +``lib_pypy/_ctypes``. Discussion and limitations ============================= @@ -123,8 +123,8 @@ To run the tests then:: - $ cd ../.. # back to pypy/ - $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests + $ cd ../../.. # back to pypy-trunk + $ ./pypy/translator/goal/pypy-c pypy/test_all.py lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests There should be 36 skipped tests and all other tests should pass. Modified: pypy/trunk/pypy/doc/docindex.txt ============================================================================== --- pypy/trunk/pypy/doc/docindex.txt (original) +++ pypy/trunk/pypy/doc/docindex.txt Thu Jun 24 12:44:22 2010 @@ -207,13 +207,6 @@ `interpreter/astcompiler/`_ interpreter-level bytecode compiler, via an AST representation -`lib/`_ PyPy's wholesale reimplementations of CPython modules_ - and experimental new application-level modules - -`lib/app_test/`_ tests for the reimplementations, running on top of CPython - -`lib/distributed/`_ distributed execution prototype, based on `transparent proxies`_ - `module/`_ contains `mixed modules`_ implementing core modules with both application and interpreter level code. Not all are finished and working. Use the ``--withmod-xxx`` Modified: pypy/trunk/pypy/doc/getting-started-python.txt ============================================================================== --- pypy/trunk/pypy/doc/getting-started-python.txt (original) +++ pypy/trunk/pypy/doc/getting-started-python.txt Thu Jun 24 12:44:22 2010 @@ -207,18 +207,18 @@ For installation purposes, note that the executable needs to be able to find its version of the Python standard library in the following three directories: ``lib-python/2.5.2``, ``lib-python/modified-2.5.2`` and -``pypy/lib``. They are located by "looking around" starting from the +``lib_pypy``. They are located by "looking around" starting from the directory in which the executable resides. The current logic is to try to find a ``PREFIX`` from which the directories ``PREFIX/lib-python/2.5.2`` and ``PREFIX/lib-python/modified.2.5.2`` and -``PREFIX/pypy/lib`` can all be found. The prefixes that are tried are:: +``PREFIX/lib_pypy`` can all be found. The prefixes that are tried are:: . - ./share/pypy-1.2 + ./lib/pypy1.2 .. - ../share/pypy-1.2 + ../lib/pypy1.2 ../.. - ../../share/pypy-1.2 + ../../lib/pypy-1.2 ../../.. etc. Modified: pypy/trunk/pypy/doc/maemo.txt ============================================================================== --- pypy/trunk/pypy/doc/maemo.txt (original) +++ pypy/trunk/pypy/doc/maemo.txt Thu Jun 24 12:44:22 2010 @@ -157,11 +157,11 @@ You can just copy your whole pypy-trunk directory over to your mobile device - however, only these should be needed:: - pypy/lib - lib-python + lib/pypy1.2/lib_pypy + lib/pypy1.2/lib-python pypy/translator/goal/pypy-c -It is neccessary that the ``pypy-c`` can find a "lib-python" and "pypy/lib" directory +It is neccessary that the ``pypy-c`` can find a "lib-python" and "lib_pypy" directory if you want to successfully startup the interpreter on the device. Start ``pypy-c`` on the device. If you see an error like "setupterm: could not find terminal" Modified: pypy/trunk/pypy/doc/objspace-proxies.txt ============================================================================== --- pypy/trunk/pypy/doc/objspace-proxies.txt (original) +++ pypy/trunk/pypy/doc/objspace-proxies.txt Thu Jun 24 12:44:22 2010 @@ -610,7 +610,7 @@ .. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py .. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py .. _`transparent.py`: ../../pypy/objspace/std/transparent.py -.. _`tputil.py`: ../../pypy/lib/tputil.py +.. _`tputil.py`: ../../lib_pypy/tputil.py .. [D12.1] `High-Level Backends and Interpreter Feature Prototypes`, PyPy EU-Report, 2007, http://codespeak.net/pypy/extradoc/eu-report/D12.1_H-L-Backends_and_Feature_Prototypes-2007-03-22.pdf Modified: pypy/trunk/pypy/doc/sandbox.txt ============================================================================== --- pypy/trunk/pypy/doc/sandbox.txt (original) +++ pypy/trunk/pypy/doc/sandbox.txt Thu Jun 24 12:44:22 2010 @@ -72,7 +72,8 @@ should do. I've successfully tried it on the JS interpreter. The controller is only called "pypy_interact" because it emulates a file hierarchy that makes pypy-c-sandbox happy - it contains (read-only) -virtual directories like /bin/lib-python and /bin/pypy/lib and it +virtual directories like /bin/lib/pypy1.2/lib-python and +/bin/lib/pypy1.2/lib_pypy and it pretends that the executable is /bin/pypy-c. Howto Modified: pypy/trunk/pypy/doc/stackless.txt ============================================================================== --- pypy/trunk/pypy/doc/stackless.txt (original) +++ pypy/trunk/pypy/doc/stackless.txt Thu Jun 24 12:44:22 2010 @@ -181,7 +181,7 @@ website. Note that Tasklets and Channels are implemented at application-level in -`pypy/lib/stackless.py`_ on top of coroutines_. You can refer to this +`lib_pypy/stackless.py`_ on top of coroutines_. You can refer to this module for more details and API documentation. The stackless.py code tries to resemble the stackless C code as much Modified: pypy/trunk/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/pypy/interpreter/baseobjspace.py Thu Jun 24 12:44:22 2010 @@ -385,6 +385,7 @@ def get_builtinmodule_to_install(self): """NOT_RPYTHON""" + from pypy.tool.lib_pypy import LIB_PYPY try: return self._builtinmodule_list except AttributeError: @@ -404,9 +405,7 @@ if not self.config.objspace.nofaking: for modname in self.ALL_BUILTIN_MODULES: - if not (os.path.exists( - os.path.join(os.path.dirname(pypy.__file__), - 'lib', modname+'.py'))): + if not LIB_PYPY.join(modname+'.py').check(file=True): modules.append('faked+'+modname) self._builtinmodule_list = modules Modified: pypy/trunk/pypy/interpreter/test/test_module.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_module.py (original) +++ pypy/trunk/pypy/interpreter/test/test_module.py Thu Jun 24 12:44:22 2010 @@ -54,11 +54,11 @@ r = repr(sys) assert r == "" - import _pypy_interact # known to be in pypy/lib + import _pypy_interact # known to be in lib_pypy r = repr(_pypy_interact) assert (r.startswith("')) nofile = type(_pypy_interact)('nofile', 'foo') assert repr(nofile) == "" Modified: pypy/trunk/pypy/interpreter/test/test_objspace.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_objspace.py (original) +++ pypy/trunk/pypy/interpreter/test/test_objspace.py Thu Jun 24 12:44:22 2010 @@ -259,3 +259,23 @@ def test_sys_import(self): from pypy.interpreter.main import run_string run_string('import sys', space=self.space) + + def test_get_builtinmodule_to_install(self): + space = self.space + try: + # force rebuilding with this fake builtin + space.ALL_BUILTIN_MODULES.append('this_doesnt_exist') + del space._builtinmodule_list + mods = space.get_builtinmodule_to_install() + + assert '__pypy__' in mods # real builtin + assert 'array' not in mods # in lib_pypy + assert 'faked+array' not in mods # in lib_pypy + assert 'this_doesnt_exist' not in mods # not in lib_pypy + assert 'faked+this_doesnt_exist' in mods # not in lib_pypy, but in + # ALL_BUILTIN_MODULES + finally: + # rebuild the original list + space.ALL_BUILTIN_MODULES.pop() + del space._builtinmodule_list + mods = space.get_builtinmodule_to_install() Modified: pypy/trunk/pypy/jit/backend/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/backend/autopath.py (original) +++ pypy/trunk/pypy/jit/backend/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/jit/backend/x86/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/autopath.py (original) +++ pypy/trunk/pypy/jit/backend/x86/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/jit/backend/x86/tool/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/tool/autopath.py (original) +++ pypy/trunk/pypy/jit/backend/x86/tool/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/jit/tl/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/tl/autopath.py (original) +++ pypy/trunk/pypy/jit/tl/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/jit/tl/spli/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/tl/spli/autopath.py (original) +++ pypy/trunk/pypy/jit/tl/spli/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/jit/tool/autopath.py ============================================================================== --- pypy/trunk/pypy/jit/tool/autopath.py (original) +++ pypy/trunk/pypy/jit/tool/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/module/_codecs/test/autopath.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/autopath.py (original) +++ pypy/trunk/pypy/module/_codecs/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/module/_sre/test/autopath.py ============================================================================== --- pypy/trunk/pypy/module/_sre/test/autopath.py (original) +++ pypy/trunk/pypy/module/_sre/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Thu Jun 24 12:44:22 2010 @@ -15,7 +15,7 @@ from pypy.module.cpyext.pyobject import RefcountState from pypy.module.cpyext.pyobject import Py_DecRef, InvalidPointerException from pypy.translator.goal import autopath -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): Modified: pypy/trunk/pypy/module/sys/__init__.py ============================================================================== --- pypy/trunk/pypy/module/sys/__init__.py (original) +++ pypy/trunk/pypy/module/sys/__init__.py Thu Jun 24 12:44:22 2010 @@ -30,9 +30,8 @@ 'stderr' : 'state.getio(space).w_stderr', '__stderr__' : 'state.getio(space).w_stderr', 'pypy_objspaceclass' : 'space.wrap(repr(space))', - #'pypy_prefix': added by pypy_initial_path() when it succeeds, pointing - # to the trunk of a checkout or to the dir /usr/share/pypy-1.1 . - + #'prefix' : # added by pypy_initial_path() when it + #'exec_prefix' : # succeeds, pointing to trunk or /usr 'path' : 'state.get(space).w_path', 'modules' : 'state.get(space).w_modules', 'argv' : 'state.get(space).w_argv', Modified: pypy/trunk/pypy/module/sys/state.py ============================================================================== --- pypy/trunk/pypy/module/sys/state.py (original) +++ pypy/trunk/pypy/module/sys/state.py Thu Jun 24 12:44:22 2010 @@ -32,26 +32,34 @@ if not stat.S_ISDIR(st[0]): raise OSError(errno.ENOTDIR, path) -def getinitialpath(srcdir): - # build the initial path from the srcdir, which is the path of - # the "dist" directory of a PyPy checkout. - from pypy.module.sys.version import CPYTHON_VERSION +def getinitialpath(prefix): + from pypy.module.sys.version import PYPY_VERSION + libdir = os.path.join(prefix, 'lib') + pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) + # search for the stdlib both in $PREFIX/lib/pypy1.2 and $PREFIX + for lib_prefix in [pypyxy_dir, prefix]: + try: + return get_importlist(lib_prefix) + except OSError: + pass + raise OSError # stdlib not foud +def get_importlist(lib_prefix): + from pypy.module.sys.version import CPYTHON_VERSION dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], CPYTHON_VERSION[1], CPYTHON_VERSION[2]) - lib_python = os.path.join(srcdir, 'lib-python') - + lib_python = os.path.join(lib_prefix, 'lib-python') python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) checkdir(python_std_lib_modified) - pypydir = os.path.join(srcdir, 'pypy') - pypy_lib = os.path.join(pypydir, 'lib') - checkdir(pypy_lib) + + lib_pypy = os.path.join(lib_prefix, 'lib_pypy') + checkdir(lib_pypy) importlist = [] - importlist.append(pypy_lib) + importlist.append(lib_pypy) importlist.append(python_std_lib_modified) importlist.append(python_std_lib) return importlist @@ -62,7 +70,9 @@ except OSError: return space.w_None else: - space.setitem(space.sys.w_dict, space.wrap('pypy_prefix'), + space.setitem(space.sys.w_dict, space.wrap('prefix'), + space.wrap(srcdir)) + space.setitem(space.sys.w_dict, space.wrap('exec_prefix'), space.wrap(srcdir)) return space.newlist([space.wrap(p) for p in path]) Modified: pypy/trunk/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/trunk/pypy/module/sys/test/autopath.py (original) +++ pypy/trunk/pypy/module/sys/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/module/sys/version.py ============================================================================== --- pypy/trunk/pypy/module/sys/version.py (original) +++ pypy/trunk/pypy/module/sys/version.py Thu Jun 24 12:44:22 2010 @@ -7,6 +7,7 @@ CPYTHON_VERSION = (2, 5, 2, "beta", 42) CPYTHON_API_VERSION = 1012 +# when changing the pypy version, remind to also change the name of trunk/lib/pypyX.Y PYPY_VERSION = (1, 2, 0, "beta", '?') # the last item is replaced by the svn revision ^^^ Modified: pypy/trunk/pypy/objspace/flow/model.py ============================================================================== --- pypy/trunk/pypy/objspace/flow/model.py (original) +++ pypy/trunk/pypy/objspace/flow/model.py Thu Jun 24 12:44:22 2010 @@ -7,7 +7,7 @@ from pypy.tool.uid import uid, Hashable from pypy.tool.descriptor import roproperty from pypy.tool.sourcetools import PY_IDENTIFIER, nice_repr_for_func -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict """ memory size before and after introduction of __slots__ Modified: pypy/trunk/pypy/pytest-A.cfg ============================================================================== --- pypy/trunk/pypy/pytest-A.cfg (original) +++ pypy/trunk/pypy/pytest-A.cfg Thu Jun 24 12:44:22 2010 @@ -1,4 +1,4 @@ -cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module', 'lib'] +cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module'] interp = ['translator/goal/pypy-c'] test_driver = ['test_all.py', '-A'] Modified: pypy/trunk/pypy/rlib/parsing/test/autopath.py ============================================================================== --- pypy/trunk/pypy/rlib/parsing/test/autopath.py (original) +++ pypy/trunk/pypy/rlib/parsing/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/rlib/rmd5.py ============================================================================== --- pypy/trunk/pypy/rlib/rmd5.py (original) +++ pypy/trunk/pypy/rlib/rmd5.py Thu Jun 24 12:44:22 2010 @@ -2,7 +2,7 @@ """ RPython implementation of MD5 checksums. -See also the pure Python implementation in pypy/lib/md5.py, which might +See also the pure Python implementation in lib_pypy/md5.py, which might or might not be faster than this one on top of CPython. This is an implementation of the MD5 hash function, Modified: pypy/trunk/pypy/rlib/rsdl/test/autopath.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/test/autopath.py (original) +++ pypy/trunk/pypy/rlib/rsdl/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/rlib/rsha.py ============================================================================== --- pypy/trunk/pypy/rlib/rsha.py (original) +++ pypy/trunk/pypy/rlib/rsha.py Thu Jun 24 12:44:22 2010 @@ -2,7 +2,7 @@ """A sample implementation of SHA-1 in RPython. - See also the pure Python implementation in pypy/lib/sha.py, which might + See also the pure Python implementation in lib_pypy/sha.py, which might or might not be faster than this one on top of CPython. Framework adapted from Dinu Gherman's MD5 implementation by Modified: pypy/trunk/pypy/rlib/rzipfile.py ============================================================================== --- pypy/trunk/pypy/rlib/rzipfile.py (original) +++ pypy/trunk/pypy/rlib/rzipfile.py Thu Jun 24 12:44:22 2010 @@ -12,7 +12,8 @@ rzlib = None # XXX hack to get crc32 to work -from pypy.lib.binascii import crc_32_tab +from pypy.tool.lib_pypy import import_from_lib_pypy +crc_32_tab = import_from_lib_pypy('binascii').crc_32_tab rcrc_32_tab = [r_uint(i) for i in crc_32_tab] Modified: pypy/trunk/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lltype.py Thu Jun 24 12:44:22 2010 @@ -9,7 +9,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.tool.uid import Hashable from pypy.tool.tls import tlsobject -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict from types import NoneType from sys import maxint import weakref Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Thu Jun 24 12:44:22 2010 @@ -21,7 +21,7 @@ from pypy.annotation import model as annmodel from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict from pypy.rpython.lltypesystem.lloperation import llop # Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_lltype.py Thu Jun 24 12:44:22 2010 @@ -1,7 +1,7 @@ import py from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.lltypesystem import lltype, rffi -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict def isweak(p, T): try: Modified: pypy/trunk/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/trunk/pypy/rpython/memory/gctypelayout.py Thu Jun 24 12:44:22 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import ll_assert -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class GCData(object): Modified: pypy/trunk/pypy/rpython/microbench/autopath.py ============================================================================== --- pypy/trunk/pypy/rpython/microbench/autopath.py (original) +++ pypy/trunk/pypy/rpython/microbench/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/rclass.py Thu Jun 24 12:44:22 2010 @@ -10,7 +10,7 @@ from pypy.rpython.exceptiondata import standardexceptions from pypy.tool.pairtype import pairtype from pypy.tool.sourcetools import func_with_new_name -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict OBJECT = ootype.ROOT META = ootype.Instance("Meta", ootype.ROOT, Modified: pypy/trunk/pypy/tool/algo/graphlib.py ============================================================================== --- pypy/trunk/pypy/tool/algo/graphlib.py (original) +++ pypy/trunk/pypy/tool/algo/graphlib.py Thu Jun 24 12:44:22 2010 @@ -6,7 +6,7 @@ 'edges' is a dict mapping vertices to a list of edges with its source. Note that we can usually use 'edges' as the set of 'vertices' too. """ -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class Edge: Modified: pypy/trunk/pypy/tool/algo/test/autopath.py ============================================================================== --- pypy/trunk/pypy/tool/algo/test/autopath.py (original) +++ pypy/trunk/pypy/tool/algo/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/tool/autopath.py ============================================================================== --- pypy/trunk/pypy/tool/autopath.py (original) +++ pypy/trunk/pypy/tool/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/tool/compat.py ============================================================================== --- pypy/trunk/pypy/tool/compat.py (original) +++ pypy/trunk/pypy/tool/compat.py Thu Jun 24 12:44:22 2010 @@ -6,5 +6,8 @@ try: from md5 import md5 except ImportError: - # no _md5 module on this platform - from pypy.lib.md5 import md5 + # no _md5 module on this platform. Try hard to find a pure-python one + # by fishing it from lib_pypy + from pypy.tool.lib_pypy import import_from_lib_pypy + md5 = import_from_lib_pypy('md5') + del import_from_lib_pypy Modified: pypy/trunk/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/trunk/pypy/tool/pytest/autopath.py (original) +++ pypy/trunk/pypy/tool/pytest/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/tool/pytest/confpath.py ============================================================================== --- pypy/trunk/pypy/tool/pytest/confpath.py (original) +++ pypy/trunk/pypy/tool/pytest/confpath.py Thu Jun 24 12:44:22 2010 @@ -1,11 +1,12 @@ import autopath import py import pypy +from pypy.tool import lib_pypy pypydir = py.path.local(pypy.__file__).dirpath() distdir = pypydir.dirpath() testresultdir = distdir.join('testresult') assert pypydir.check(dir=1) -libpythondir = distdir.join('lib-python') -regrtestdir = libpythondir.join('2.5.2', 'test') -modregrtestdir = libpythondir.join('modified-2.5.2', 'test') +libpythondir = lib_pypy.LIB_PYTHON +regrtestdir = lib_pypy.LIB_PYTHON_VANILLA.join('test') +modregrtestdir = lib_pypy.LIB_PYTHON_MODIFIED.join('test') Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Thu Jun 24 12:44:22 2010 @@ -46,14 +46,13 @@ raise PyPyCNotFound('Please compile pypy first, using translate.py') builddir = udir.ensure("build", dir=True) pypydir = builddir.ensure(name, dir=True) + # Careful: to copy lib_pypy, copying just the svn-tracked files + # would not be enough: there are also ctypes_config_cache/_*_cache.py. shutil.copytree(str(basedir.join('lib-python')), str(pypydir.join('lib-python')), - ignore=ignore_patterns('.svn', '*.pyc', '*~')) - # Careful: to copy pypy/lib, copying just the svn-tracked files - # would not be enough: there are also ctypes_config_cache/_*_cache.py. - pypydir.ensure('pypy', dir=True) - shutil.copytree(str(basedir.join('pypy', 'lib')), - str(pypydir.join('pypy', 'lib')), + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + shutil.copytree(str(basedir.join('lib_pypy')), + str(pypydir.join('lib_pypy')), ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) Modified: pypy/trunk/pypy/tool/release/test/test_package.py ============================================================================== --- pypy/trunk/pypy/tool/release/test/test_package.py (original) +++ pypy/trunk/pypy/tool/release/test/test_package.py Thu Jun 24 12:44:22 2010 @@ -2,6 +2,7 @@ import py from pypy.tool.autopath import pypydir from pypy.tool.release.package import package +from pypy.module.sys.version import CPYTHON_VERSION import tarfile, os def test_dir_structure(): @@ -14,15 +15,17 @@ fake_pypy_c = False try: builddir = package(py.path.local(pypydir).dirpath(), 'test') - assert builddir.join('test', 'lib-python', '2.5.2', 'test').check() - assert builddir.join('test', 'bin', 'pypy-c').check() - assert builddir.join('test', 'pypy', 'lib', 'syslog.py').check() - assert not builddir.join('test', 'pypy', 'lib', 'py').check() - assert not builddir.join('test', 'pypy', 'lib', 'ctypes_configure').check() - assert builddir.join('test', 'LICENSE').check() - assert builddir.join('test', 'README').check() + prefix = builddir.join('test') + cpyver = '%d.%d.%d' % CPYTHON_VERSION[:3] + assert prefix.join('lib-python', cpyver, 'test').check() + assert prefix.join('bin', 'pypy-c').check() + assert prefix.join('lib_pypy', 'syslog.py').check() + assert not prefix.join('lib_pypy', 'py').check() + assert not prefix.join('lib_pypy', 'ctypes_configure').check() + assert prefix.join('LICENSE').check() + assert prefix.join('README').check() th = tarfile.open(str(builddir.join('test.tar.bz2'))) - assert th.getmember('test/pypy/lib/syslog.py') + assert th.getmember('test/lib_pypy/syslog.py') finally: if fake_pypy_c: pypy_c.remove() Modified: pypy/trunk/pypy/tool/stdlib___future__.py ============================================================================== --- pypy/trunk/pypy/tool/stdlib___future__.py (original) +++ pypy/trunk/pypy/tool/stdlib___future__.py Thu Jun 24 12:44:22 2010 @@ -1,8 +1,8 @@ # load __future__.py constants def load_module(): - import py - module_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/2.5.2/__future__.py') + from pypy.tool.lib_pypy import LIB_PYTHON_VANILLA + module_path = LIB_PYTHON_VANILLA.join('__future__.py') execfile(str(module_path), globals()) load_module() Modified: pypy/trunk/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/trunk/pypy/tool/stdlib_opcode.py (original) +++ pypy/trunk/pypy/tool/stdlib_opcode.py Thu Jun 24 12:44:22 2010 @@ -106,8 +106,8 @@ opmap as host_opmap, HAVE_ARGUMENT as host_HAVE_ARGUMENT) def load_pypy_opcode(): - import py - opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.5.2/opcode.py') + from pypy.tool.lib_pypy import LIB_PYTHON_MODIFIED + opcode_path = LIB_PYTHON_MODIFIED.join('opcode.py') d = {} execfile(str(opcode_path), d) for name in __all__: Modified: pypy/trunk/pypy/tool/test/autopath.py ============================================================================== --- pypy/trunk/pypy/tool/test/autopath.py (original) +++ pypy/trunk/pypy/tool/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/autopath.py (original) +++ pypy/trunk/pypy/translator/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/benchmark/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/benchmark/autopath.py (original) +++ pypy/trunk/pypy/translator/benchmark/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/c/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/c/autopath.py (original) +++ pypy/trunk/pypy/translator/c/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/c/database.py ============================================================================== --- pypy/trunk/pypy/translator/c/database.py (original) +++ pypy/trunk/pypy/translator/c/database.py Thu Jun 24 12:44:22 2010 @@ -16,7 +16,7 @@ from pypy.translator.c.extfunc import do_the_getting from pypy import conftest from pypy.translator.c import gc -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class NoCorrespondingNode(Exception): Modified: pypy/trunk/pypy/translator/c/funcgen.py ============================================================================== --- pypy/trunk/pypy/translator/c/funcgen.py (original) +++ pypy/trunk/pypy/translator/c/funcgen.py Thu Jun 24 12:44:22 2010 @@ -13,7 +13,7 @@ from pypy.rpython.lltypesystem.llmemory import Address from pypy.translator.backendopt.ssa import SSI_to_SSA from pypy.translator.backendopt.innerloop import find_inner_loops -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict PyObjPtr = Ptr(PyObject) Modified: pypy/trunk/pypy/translator/c/gcc/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/autopath.py (original) +++ pypy/trunk/pypy/translator/c/gcc/autopath.py Thu Jun 24 12:44:22 2010 @@ -37,8 +37,7 @@ partdir = head head, tail = os.path.split(head) if tail == part: - # check if "../py/__init__.py" exists - checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') if not os.path.exists(checkfile): error = "Cannot find %r" % (os.path.normpath(checkfile),) break @@ -127,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/c/test/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/autopath.py (original) +++ pypy/trunk/pypy/translator/c/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/cli/test/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/cli/test/autopath.py (original) +++ pypy/trunk/pypy/translator/cli/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/geninterplevel.py ============================================================================== --- pypy/trunk/pypy/translator/geninterplevel.py (original) +++ pypy/trunk/pypy/translator/geninterplevel.py Thu Jun 24 12:44:22 2010 @@ -62,7 +62,7 @@ from pypy.translator.gensupp import ordered_blocks, UniqueList, builtin_base, \ uniquemodulename, C_IDENTIFIER, NameManager -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict import pypy # __path__ import py.path @@ -496,21 +496,22 @@ need_extra_path = True name = self.uniquename('mod_%s' % value.__name__) if need_extra_path: - self.initcode.append1('import pypy') - self.initcode.append1('import sys') - self.initcode.append1('import os') - self.initcode.append1('for pkgdir in pypy.__path__:\n' - ' libdir = os.path.join(pkgdir, "lib")\n' - ' if os.path.isdir(libdir):\n' - ' break\n' - 'else:\n' - ' raise Exception, "cannot find pypy/lib directory"\n' - 'sys.path.insert(0, libdir)\n') - self.initcode.append1('try:\n' - ' import %s as _tmp\n' - 'finally:\n' - ' if libdir in sys.path:\n' - ' sys.path.remove(libdir)\n' % value.__name__) + assert False + ## self.initcode.append1('import pypy') + ## self.initcode.append1('import sys') + ## self.initcode.append1('import os') + ## self.initcode.append1('for pkgdir in pypy.__path__:\n' + ## ' libdir = os.path.join(pkgdir, "lib")\n' + ## ' if os.path.isdir(libdir):\n' + ## ' break\n' + ## 'else:\n' + ## ' raise Exception, "cannot find pypy/lib directory"\n' + ## 'sys.path.insert(0, libdir)\n') + ## self.initcode.append1('try:\n' + ## ' import %s as _tmp\n' + ## 'finally:\n' + ## ' if libdir in sys.path:\n' + ## ' sys.path.remove(libdir)\n' % value.__name__) else: self.initcode.append1('import %s as _tmp' % value.__name__) self.initcode.append1('%s = space.wrap(_tmp)' % (name)) @@ -1473,6 +1474,7 @@ dic = initfunc(space) # and now use the members of the dict """ + from pypy.tool.lib_pypy import LIB_PYPY # create something like a module if type(sourcetext) is str: code = py.code.Source(sourcetext).compile() @@ -1484,12 +1486,7 @@ dic['__file__'] = filename # XXX allow the app-level code to contain e.g. "import _formatting" - for pkgdir in pypy.__path__: - libdir = os.path.join(pkgdir, "lib") - if os.path.isdir(libdir): - break - else: - raise Exception, "cannot find pypy/lib directory" + libdir = str(LIB_PYPY) sys.path.insert(0, libdir) try: if faked_set: Modified: pypy/trunk/pypy/translator/goal/app_main.py ============================================================================== --- pypy/trunk/pypy/translator/goal/app_main.py (original) +++ pypy/trunk/pypy/translator/goal/app_main.py Thu Jun 24 12:44:22 2010 @@ -182,12 +182,27 @@ option) return argv[i], i +def get_library_path(executable): + search = executable + while 1: + dirname = resolvedirof(search) + if dirname == search: + # not found! let's hope that the compiled-in path is ok + print >> sys.stderr, ('debug: WARNING: library path not found, ' + 'using compiled-in sys.path') + newpath = sys.path[:] + break + newpath = sys.pypy_initial_path(dirname) + if newpath is None: + search = dirname # walk to the parent directory + continue + break # found! + return newpath def setup_initial_paths(executable, nanos): # a substituted os if we are translated global os os = nanos - AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d' # find the full path to the executable, assuming that if there is no '/' # in the provided one then we must look along the $PATH if we_are_translated() and IS_WINDOWS and not executable.lower().endswith('.exe'): @@ -204,24 +219,7 @@ break sys.executable = os.path.abspath(executable) - # set up a sys.path that depends on the local machine - autosubpath = AUTOSUBPATH % sys.pypy_version_info[:2] - search = executable - while 1: - dirname = resolvedirof(search) - if dirname == search: - # not found! let's hope that the compiled-in path is ok - print >> sys.stderr, ('debug: WARNING: library path not found, ' - 'using compiled-in sys.path') - newpath = sys.path[:] - break - newpath = sys.pypy_initial_path(dirname) - if newpath is None: - newpath = sys.pypy_initial_path(os.path.join(dirname, autosubpath)) - if newpath is None: - search = dirname # walk to the parent directory - continue - break # found! + newpath = get_library_path(executable) path = os.getenv('PYTHONPATH') if path: newpath = path.split(os.pathsep) + newpath Modified: pypy/trunk/pypy/translator/goal/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/goal/autopath.py (original) +++ pypy/trunk/pypy/translator/goal/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/trunk/pypy/translator/goal/targetpypystandalone.py Thu Jun 24 12:44:22 2010 @@ -225,7 +225,8 @@ return PyPyJitPolicy() def get_entry_point(self, config): - from pypy.lib.ctypes_config_cache import rebuild + from pypy.tool.lib_pypy import import_from_lib_pypy + rebuild = import_from_lib_pypy('ctypes_config_cache/rebuild') rebuild.try_rebuild() space = make_objspace(config) Modified: pypy/trunk/pypy/translator/goal/test2/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/goal/test2/autopath.py (original) +++ pypy/trunk/pypy/translator/goal/test2/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/trunk/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/trunk/pypy/translator/goal/test2/test_app_main.py Thu Jun 24 12:44:22 2010 @@ -460,3 +460,59 @@ data = child_out_err.read(11) assert data == '\x00(STDOUT)\n\x00' # from stdout child_out_err.close() + + +class AppTestAppMain: + + def setup_class(self): + # ------------------------------------ + # setup code for test_get_library_path + # ------------------------------------ + from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION + libroot = 'lib/pypy%d.%d' % PYPY_VERSION[:2] + cpy_ver = '%d.%d.%d' % CPYTHON_VERSION[:3] + + goal_dir = os.path.dirname(app_main) + # build a directory hierarchy like which contains both bin/pypy-c and + # lib/pypy1.2/* + prefix = udir.join('pathtest') + fake_exe = prefix.join('bin/pypy-c').ensure(file=1) + pypyxy = prefix.join(libroot).ensure(dir=1) + expected_path = [str(pypyxy.join(subdir).ensure(dir=1)) + for subdir in ('lib_pypy', + 'lib-python/modified-%s' % cpy_ver, + 'lib-python/%s' % cpy_ver)] + + self.w_goal_dir = self.space.wrap(goal_dir) + self.w_fake_exe = self.space.wrap(str(fake_exe)) + self.w_expected_path = self.space.wrap(expected_path) + self.w_trunkdir = self.space.wrap(os.path.dirname(autopath.pypydir)) + + def test_get_library_path(self): + import sys + import os + sys.path.append(self.goal_dir) + try: + import app_main + app_main.os = os + newpath = app_main.get_library_path('/tmp/pypy-c') # stdlib not found + assert newpath == sys.path + newpath = app_main.get_library_path(self.fake_exe) + assert newpath == self.expected_path + finally: + sys.path.pop() + + def test_trunk_can_be_prefix(self): + import sys + import os + sys.path.append(self.goal_dir) + try: + import app_main + app_main.os = os + pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c') + newpath = app_main.get_library_path(pypy_c) + assert len(newpath) == 3 + for p in newpath: + assert p.startswith(self.trunkdir) + finally: + sys.path.pop() Modified: pypy/trunk/pypy/translator/microbench/pybench/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/microbench/pybench/autopath.py (original) +++ pypy/trunk/pypy/translator/microbench/pybench/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/oosupport/function.py ============================================================================== --- pypy/trunk/pypy/translator/oosupport/function.py (original) +++ pypy/trunk/pypy/translator/oosupport/function.py Thu Jun 24 12:44:22 2010 @@ -7,7 +7,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.treebuilder import SubOperation from pypy.translator.oosupport.metavm import InstructionList, StoreResult -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict def render_sub_op(sub_op, db, generator): Modified: pypy/trunk/pypy/translator/sandbox/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/autopath.py (original) +++ pypy/trunk/pypy/translator/sandbox/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/pypy_interact.py (original) +++ pypy/trunk/pypy/translator/sandbox/pypy_interact.py Thu Jun 24 12:44:22 2010 @@ -26,6 +26,7 @@ from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile +from pypy.tool.lib_pypy import LIB_ROOT class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): debug = True @@ -50,17 +51,15 @@ tmpdirnode = Dir({}) else: tmpdirnode = RealDir(self.tmpdir, exclude=exclude) - pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) + libroot = str(LIB_ROOT) return Dir({ 'bin': Dir({ 'pypy-c': RealFile(self.executable), - 'lib-python': RealDir(os.path.join(pypydist, 'lib-python'), + 'lib-python': RealDir(os.path.join(libroot, 'lib-python'), + exclude=exclude), + 'lib_pypy': RealDir(os.path.join(libroot, 'lib_pypy'), exclude=exclude), - 'pypy': Dir({ - 'lib': RealDir(os.path.join(pypydist, 'pypy', 'lib'), - exclude=exclude), - }), }), 'tmp': tmpdirnode, }) Modified: pypy/trunk/pypy/translator/sandbox/sandlib.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/sandlib.py (original) +++ pypy/trunk/pypy/translator/sandbox/sandlib.py Thu Jun 24 12:44:22 2010 @@ -6,7 +6,6 @@ import py import sys, os, posixpath, errno, stat, time -from pypy.lib import marshal # see below from pypy.rpython.module.ll_os_stat import s_StatResult from pypy.tool.ansi_print import AnsiLog from pypy.rlib.rarithmetic import r_longlong @@ -26,12 +25,14 @@ py.log.setconsumer("sandlib", MyAnsiLog()) -# Note: we use pypy.lib.marshal instead of the built-in marshal +# Note: we use lib_pypy/marshal.py instead of the built-in marshal # for two reasons. The built-in module could be made to segfault # or be attackable in other ways by sending malicious input to # load(). Also, marshal.load(f) blocks with the GIL held when # f is a pipe with no data immediately avaialble, preventing the # _waiting_thread to run. +from pypy.tool.lib_pypy import import_from_lib_pypy +marshal = import_from_lib_pypy('marshal') def read_message(f, timeout=None): # warning: 'timeout' is not really reliable and should only be used Modified: pypy/trunk/pypy/translator/sandbox/test/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/autopath.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/sandbox/test/test_pypy_interact.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/test_pypy_interact.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/test_pypy_interact.py Thu Jun 24 12:44:22 2010 @@ -24,7 +24,7 @@ assert_(argv[0] == '/bin/pypy-c', "bad argv[0]") st = os.lstat('/bin/pypy-c') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for /bin/pypy-c") - for dirname in ['/bin/lib-python/2.5.2', '/bin/pypy/lib']: + for dirname in ['/bin/lib-python/2.5.2', '/bin/lib_pypy']: st = os.stat(dirname) assert_(stat.S_ISDIR(st.st_mode), "bad st_mode for " + dirname) assert_(os.environ.get('PYTHONPATH') is None, "unexpected $PYTHONPATH") @@ -70,7 +70,7 @@ def setup_module(mod): t = Translation(mini_pypy_like_entry_point, backend='c', - standalone=True, sandbox=True) + standalone=True, sandbox=True) mod.executable = str(t.compile()) Modified: pypy/trunk/pypy/translator/test/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/test/autopath.py (original) +++ pypy/trunk/pypy/translator/test/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/tool/autopath.py ============================================================================== --- pypy/trunk/pypy/translator/tool/autopath.py (original) +++ pypy/trunk/pypy/translator/tool/autopath.py Thu Jun 24 12:44:22 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/trunk/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/trunk/pypy/translator/tool/lltracker.py (original) +++ pypy/trunk/pypy/translator/tool/lltracker.py Thu Jun 24 12:44:22 2010 @@ -8,7 +8,7 @@ from pypy.rpython.memory.gcheader import header2obj from pypy.translator.tool.reftracker import BaseRefTrackerPage, MARKER from pypy.tool.uid import uid -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class LLRefTrackerPage(BaseRefTrackerPage): From antocuni at codespeak.net Thu Jun 24 12:58:35 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jun 2010 12:58:35 +0200 (CEST) Subject: [pypy-svn] r75557 - pypy/trunk/pypy/lib Message-ID: <20100624105835.7EFF336C536@codespeak.net> Author: antocuni Date: Thu Jun 24 12:58:33 2010 New Revision: 75557 Removed: pypy/trunk/pypy/lib/ Log: remove pypy/lib, as it has been moved to lib_pypy during the merge of the sys-prefix branch. It should have been deleted in the merge, I don't know why it didn't happen From afa at codespeak.net Thu Jun 24 16:59:03 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 24 Jun 2010 16:59:03 +0200 (CEST) Subject: [pypy-svn] r75558 - pypy/trunk/pypy/rlib/test Message-ID: <20100624145903.966FE282B9C@codespeak.net> Author: afa Date: Thu Jun 24 16:59:01 2010 New Revision: 75558 Modified: pypy/trunk/pypy/rlib/test/test_runicode.py Log: Fix these tests on Windows, where sizeof(UniChar)==2. Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Thu Jun 24 16:59:01 2010 @@ -5,11 +5,14 @@ def test_unichr(): a = runicode.UNICHR(0xffff) assert a == u'\uffff' - a = runicode.UNICHR(0x10000) - if sys.maxunicode < 0x10000: - assert len(a) == 2 # surrogates + if runicode.MAXUNICODE > 0xffff: + a = runicode.UNICHR(0x10000) + if sys.maxunicode < 0x10000: + assert len(a) == 2 # surrogates + else: + assert len(a) == 1 else: - assert len(a) == 1 + py.test.raises(ValueError, runicode.UNICHR, 0x10000) class UnicodeTests(object): @@ -228,7 +231,7 @@ class TestTranslation(object): def setup_class(cls): - if len(runicode.UNICHR(0x10000)) == 2: + if runicode.MAXUNICODE != sys.maxunicode: py.test.skip("these tests cannot run on the llinterp") def test_utf8(self): From benjamin at codespeak.net Thu Jun 24 18:00:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 24 Jun 2010 18:00:09 +0200 (CEST) Subject: [pypy-svn] r75559 - in pypy/branch/fast-forward: . lib-python lib-python/modified-2.5.2 lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command lib-python/modified-2.5.2/test lib_pypy pypy pypy/annotation pypy/annotation/test pypy/bin pypy/config pypy/doc pypy/doc/config pypy/interpreter pypy/interpreter/test pypy/jit/backend pypy/jit/backend/x86 pypy/jit/backend/x86/tool pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/lib pypy/module pypy/module/__builtin__/test pypy/module/_codecs/test pypy/module/_sre/test pypy/module/cpyext pypy/module/cpyext/test pypy/module/sys pypy/module/sys/test pypy/module/test_lib_pypy pypy/module/test_lib_pypy/ctypes_tests pypy/module/test_lib_pypy/test_distributed pypy/objspace/flow pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/parsing/test pypy/rlib/rsdl/test pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory pypy/rpython/microbench pypy/rpython/ootypesystem pypy/tool pypy/tool/algo pypy/tool/algo/test pypy/tool/pytest pypy/tool/release pypy/tool/release/test pypy/tool/test pypy/translator pypy/translator/backendopt/test pypy/translator/benchmark pypy/translator/c pypy/translator/c/gcc pypy/translator/c/src pypy/translator/c/test pypy/translator/cli/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/microbench/pybench pypy/translator/oosupport pypy/translator/sandbox pypy/translator/sandbox/test pypy/translator/test pypy/translator/tool site-packages Message-ID: <20100624160009.29813282B9C@codespeak.net> Author: benjamin Date: Thu Jun 24 18:00:01 2010 New Revision: 75559 Added: pypy/branch/fast-forward/lib_pypy/ - copied from r75539, pypy/branch/fast-forward/pypy/lib/ pypy/branch/fast-forward/pypy/module/conftest.py - copied unchanged from r75557, pypy/trunk/pypy/module/conftest.py pypy/branch/fast-forward/pypy/module/sys/test/test_initialpath.py - copied unchanged from r75557, pypy/trunk/pypy/module/sys/test/test_initialpath.py pypy/branch/fast-forward/pypy/module/test_lib_pypy/ (props changed) - copied from r75557, pypy/trunk/pypy/module/test_lib_pypy/ pypy/branch/fast-forward/pypy/tool/identity_dict.py - copied unchanged from r75557, pypy/trunk/pypy/tool/identity_dict.py pypy/branch/fast-forward/pypy/tool/lib_pypy.py - copied unchanged from r75557, pypy/trunk/pypy/tool/lib_pypy.py pypy/branch/fast-forward/pypy/tool/test/test_identitydict.py - copied unchanged from r75557, pypy/trunk/pypy/tool/test/test_identitydict.py pypy/branch/fast-forward/pypy/tool/test/test_lib_pypy.py - copied unchanged from r75557, pypy/trunk/pypy/tool/test/test_lib_pypy.py pypy/branch/fast-forward/site-packages/ - copied from r75557, pypy/trunk/site-packages/ Removed: pypy/branch/fast-forward/pypy/jit/tl/run_all_tests.py pypy/branch/fast-forward/pypy/lib/ Modified: pypy/branch/fast-forward/ (props changed) pypy/branch/fast-forward/lib-python/conftest.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/cmd.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/install.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig.py pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/branch/fast-forward/lib-python/modified-2.5.2/site.py pypy/branch/fast-forward/lib-python/modified-2.5.2/test/regrtest.py pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_doctest.py pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_sys.py pypy/branch/fast-forward/pypy/annotation/bookkeeper.py pypy/branch/fast-forward/pypy/annotation/test/autopath.py pypy/branch/fast-forward/pypy/bin/autopath.py pypy/branch/fast-forward/pypy/bin/py.py pypy/branch/fast-forward/pypy/config/autopath.py pypy/branch/fast-forward/pypy/config/pypyoption.py pypy/branch/fast-forward/pypy/conftest.py pypy/branch/fast-forward/pypy/doc/_ref.txt pypy/branch/fast-forward/pypy/doc/coding-guide.txt pypy/branch/fast-forward/pypy/doc/config/autopath.py pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.md5.txt pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.sha.txt pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.struct.txt pypy/branch/fast-forward/pypy/doc/cpython_differences.txt pypy/branch/fast-forward/pypy/doc/ctypes-implementation.txt pypy/branch/fast-forward/pypy/doc/docindex.txt pypy/branch/fast-forward/pypy/doc/getting-started-python.txt pypy/branch/fast-forward/pypy/doc/maemo.txt pypy/branch/fast-forward/pypy/doc/objspace-proxies.txt pypy/branch/fast-forward/pypy/doc/release-1.3.0.txt pypy/branch/fast-forward/pypy/doc/sandbox.txt pypy/branch/fast-forward/pypy/doc/stackless.txt pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py pypy/branch/fast-forward/pypy/interpreter/test/test_module.py pypy/branch/fast-forward/pypy/interpreter/test/test_objspace.py pypy/branch/fast-forward/pypy/jit/backend/autopath.py pypy/branch/fast-forward/pypy/jit/backend/x86/autopath.py pypy/branch/fast-forward/pypy/jit/backend/x86/tool/autopath.py pypy/branch/fast-forward/pypy/jit/tl/autopath.py pypy/branch/fast-forward/pypy/jit/tl/spli/autopath.py pypy/branch/fast-forward/pypy/jit/tool/autopath.py pypy/branch/fast-forward/pypy/module/__builtin__/test/autopath.py pypy/branch/fast-forward/pypy/module/_codecs/test/autopath.py pypy/branch/fast-forward/pypy/module/_sre/test/autopath.py pypy/branch/fast-forward/pypy/module/cpyext/api.py pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py pypy/branch/fast-forward/pypy/module/sys/__init__.py pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py pypy/branch/fast-forward/pypy/module/sys/state.py pypy/branch/fast-forward/pypy/module/sys/test/autopath.py pypy/branch/fast-forward/pypy/module/sys/version.py pypy/branch/fast-forward/pypy/module/test_lib_pypy/ctypes_tests/ (props changed) pypy/branch/fast-forward/pypy/module/test_lib_pypy/test_distributed/ (props changed) pypy/branch/fast-forward/pypy/objspace/flow/model.py pypy/branch/fast-forward/pypy/objspace/std/floatobject.py pypy/branch/fast-forward/pypy/objspace/std/test/test_floatobject.py pypy/branch/fast-forward/pypy/pytest-A.cfg pypy/branch/fast-forward/pypy/rlib/parsing/test/autopath.py pypy/branch/fast-forward/pypy/rlib/rmd5.py pypy/branch/fast-forward/pypy/rlib/rsdl/test/autopath.py pypy/branch/fast-forward/pypy/rlib/rsha.py pypy/branch/fast-forward/pypy/rlib/rzipfile.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py pypy/branch/fast-forward/pypy/rpython/microbench/autopath.py pypy/branch/fast-forward/pypy/rpython/ootypesystem/rclass.py pypy/branch/fast-forward/pypy/tool/algo/graphlib.py pypy/branch/fast-forward/pypy/tool/algo/test/autopath.py pypy/branch/fast-forward/pypy/tool/autopath.py pypy/branch/fast-forward/pypy/tool/compat.py pypy/branch/fast-forward/pypy/tool/pytest/autopath.py pypy/branch/fast-forward/pypy/tool/pytest/confpath.py pypy/branch/fast-forward/pypy/tool/release/package.py pypy/branch/fast-forward/pypy/tool/release/test/test_package.py pypy/branch/fast-forward/pypy/tool/stdlib___future__.py pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py pypy/branch/fast-forward/pypy/tool/test/autopath.py pypy/branch/fast-forward/pypy/translator/autopath.py pypy/branch/fast-forward/pypy/translator/backendopt/test/test_mallocprediction.py pypy/branch/fast-forward/pypy/translator/benchmark/autopath.py pypy/branch/fast-forward/pypy/translator/c/autopath.py pypy/branch/fast-forward/pypy/translator/c/database.py pypy/branch/fast-forward/pypy/translator/c/funcgen.py pypy/branch/fast-forward/pypy/translator/c/gcc/autopath.py pypy/branch/fast-forward/pypy/translator/c/src/support.h pypy/branch/fast-forward/pypy/translator/c/test/autopath.py pypy/branch/fast-forward/pypy/translator/c/test/test_typed.py pypy/branch/fast-forward/pypy/translator/cli/test/autopath.py pypy/branch/fast-forward/pypy/translator/geninterplevel.py pypy/branch/fast-forward/pypy/translator/goal/app_main.py pypy/branch/fast-forward/pypy/translator/goal/autopath.py pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py pypy/branch/fast-forward/pypy/translator/goal/test2/autopath.py pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py pypy/branch/fast-forward/pypy/translator/microbench/pybench/autopath.py pypy/branch/fast-forward/pypy/translator/oosupport/function.py pypy/branch/fast-forward/pypy/translator/sandbox/autopath.py pypy/branch/fast-forward/pypy/translator/sandbox/pypy_interact.py pypy/branch/fast-forward/pypy/translator/sandbox/sandlib.py pypy/branch/fast-forward/pypy/translator/sandbox/test/autopath.py pypy/branch/fast-forward/pypy/translator/sandbox/test/test_pypy_interact.py pypy/branch/fast-forward/pypy/translator/test/autopath.py pypy/branch/fast-forward/pypy/translator/tool/autopath.py pypy/branch/fast-forward/pypy/translator/tool/lltracker.py Log: merge from trunk Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Thu Jun 24 18:00:01 2010 @@ -21,8 +21,8 @@ regrtestdir, modregrtestdir, testresultdir pytest_plugins = "resultlog", -rsyncdirs = ['.', '../pypy'] - +rsyncdirs = ['.', '../pypy/'] + # # Interfacing/Integrating with py.test's collection process # Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/cmd.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/cmd.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/cmd.py Thu Jun 24 18:00:01 2010 @@ -18,7 +18,8 @@ # return a list of 'site' dirs for easy_install from pkg_resources import normalize_path sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep)) - sitedirs.append(os.path.join(sys.pypy_prefix, 'site-packages')) + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedirs.append(os.path.join(sys.prefix, 'lib', pypylib, 'site-packages')) sitedirs = map(normalize_path, sitedirs) return sitedirs Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/build_ext.py Thu Jun 24 18:00:01 2010 @@ -167,7 +167,7 @@ # for Release and Debug builds. # also Python's library directory must be appended to library_dirs if os.name == 'nt': - self.library_dirs.append(os.path.join(sys.pypy_prefix, 'pypy', '_interfaces')) + self.library_dirs.append(os.path.join(sys.prefix, 'pypy', '_interfaces')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/install.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/install.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/command/install.py Thu Jun 24 18:00:01 2010 @@ -67,8 +67,8 @@ 'data' : '$base', }, 'pypy': { - 'purelib': '$base/site-packages', - 'platlib': '$base/site-packages', + 'purelib': '$base/lib/pypy$pypy_version_short/site-packages', + 'platlib': '$base/lib/pypy$pypy_version_short/site-packages', 'headers': '$base/include', 'scripts': '$base/bin', 'data' : '$base', @@ -283,6 +283,7 @@ 'dist_fullname': self.distribution.get_fullname(), 'py_version': py_version, 'py_version_short': py_version[0:3], + 'pypy_version_short': '%d.%d' % sys.pypy_version_info[:2], 'sys_prefix': prefix, 'prefix': prefix, 'sys_exec_prefix': exec_prefix, @@ -391,13 +392,9 @@ if self.exec_prefix is not None: raise DistutilsOptionError, \ "must not supply exec-prefix without prefix" - - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - self.exec_prefix = self.prefix - else: - self.prefix = os.path.normpath(sys.prefix) - self.exec_prefix = os.path.normpath(sys.exec_prefix) + + self.prefix = os.path.normpath(sys.prefix) + self.exec_prefix = os.path.normpath(sys.exec_prefix) else: if self.exec_prefix is None: @@ -417,10 +414,7 @@ self.select_scheme("unix_home") else: if self.prefix is None: - if hasattr(sys, 'pypy_prefix'): - self.prefix = os.path.normpath(sys.pypy_prefix) - else: - self.prefix = os.path.normpath(sys.prefix) + self.prefix = os.path.normpath(sys.prefix) self.install_base = self.install_platbase = self.prefix try: @@ -434,7 +428,7 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! - if hasattr(sys, 'pypy_prefix'): + if hasattr(sys, 'pypy_version_info'): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig.py Thu Jun 24 18:00:01 2010 @@ -19,5 +19,7 @@ if '__pypy__' in sys.builtin_module_names: from distutils.sysconfig_pypy import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools else: from distutils.sysconfig_cpython import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Thu Jun 24 18:00:01 2010 @@ -7,7 +7,7 @@ from distutils.errors import DistutilsPlatformError -PYPY_PREFIX = os.path.normpath(sys.pypy_prefix) +PREFIX = os.path.normpath(sys.prefix) python_build = False @@ -17,8 +17,8 @@ if os.path.exists(cand): return cand if plat_specific: - return j(sys.pypy_prefix, "pypy", "_interfaces") - return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include') + return j(sys.prefix, "pypy", "_interfaces") + return j(sys.prefix, 'pypy', 'module', 'cpyext', 'include') def get_python_version(): """Return a string containing the major and minor Python version, @@ -46,8 +46,9 @@ raise DistutilsPlatformError( "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: - prefix = PYPY_PREFIX - return os.path.join(prefix, "site-packages") + prefix = PREFIX + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + return os.path.join(prefix, 'lib', pypylib, 'site-packages') _config_vars = None Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/site.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/site.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/site.py Thu Jun 24 18:00:01 2010 @@ -175,8 +175,9 @@ def addsitepackages(known_paths): """Add site-packages to sys.path, in a PyPy-specific way.""" - if hasattr(sys, 'pypy_prefix'): - sitedir = os.path.join(sys.pypy_prefix, "site-packages") + if hasattr(sys, 'pypy_version_info'): + pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] + sitedir = os.path.join(sys.prefix, 'lib', pypylib, 'site-packages') if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) return None Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/test/regrtest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/test/regrtest.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/test/regrtest.py Thu Jun 24 18:00:01 2010 @@ -348,11 +348,8 @@ random.shuffle(tests) if trace: import trace - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=False, count=True) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], + trace=False, count=True) test_support.verbose = verbose # Tell tests to be moderately quiet test_support.use_resources = use_resources save_modules = sys.modules.keys() Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_doctest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_doctest.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_doctest.py Thu Jun 24 18:00:01 2010 @@ -2422,11 +2422,8 @@ import trace, sys, re, StringIO def test_coverage(coverdir): - if hasattr(sys, 'prefix'): - ignoredirs = [sys.prefix, sys.exec_prefix] - else: - ignoredirs = [sys.pypy_prefix] # PyPy only - tracer = trace.Trace(ignoredirs=ignoredirs, trace=0, count=1) + tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,], + trace=0, count=1) tracer.run('reload(doctest); test_main()') r = tracer.results() print 'Writing coverage results...' Modified: pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_sys.py ============================================================================== --- pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_sys.py (original) +++ pypy/branch/fast-forward/lib-python/modified-2.5.2/test/test_sys.py Thu Jun 24 18:00:01 2010 @@ -334,11 +334,8 @@ if test.test_support.have_unicode: self.assert_(isinstance(sys.maxunicode, int)) self.assert_(isinstance(sys.platform, basestring)) - if hasattr(sys, 'prefix'): - self.assert_(isinstance(sys.prefix, basestring)) - self.assert_(isinstance(sys.exec_prefix, basestring)) - else: - self.assert_(isinstance(sys.pypy_prefix, basestring)) # PyPy only + self.assert_(isinstance(sys.prefix, basestring)) + self.assert_(isinstance(sys.exec_prefix, basestring)) self.assert_(isinstance(sys.version, basestring)) vi = sys.version_info self.assert_(isinstance(vi, tuple)) Modified: pypy/branch/fast-forward/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/bookkeeper.py (original) +++ pypy/branch/fast-forward/pypy/annotation/bookkeeper.py Thu Jun 24 18:00:01 2010 @@ -22,7 +22,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype from pypy.rpython import extregistry -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class Stats: Modified: pypy/branch/fast-forward/pypy/annotation/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/annotation/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/annotation/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/bin/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/bin/autopath.py (original) +++ pypy/branch/fast-forward/pypy/bin/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/bin/py.py ============================================================================== --- pypy/branch/fast-forward/pypy/bin/py.py (original) +++ pypy/branch/fast-forward/pypy/bin/py.py Thu Jun 24 18:00:01 2010 @@ -11,6 +11,7 @@ except ImportError: pass +import pypy from pypy.tool import option from optparse import make_option from pypy.interpreter import main, interactive, error, gateway @@ -84,6 +85,14 @@ space.setitem(space.sys.w_dict, space.wrap('executable'), space.wrap(argv[0])) + # call pypy_initial_path: the side-effect is that it sets sys.prefix and + # sys.exec_prefix + srcdir = os.path.dirname(os.path.dirname(pypy.__file__)) + space.appexec([space.wrap(srcdir)], """(srcdir): + import sys + sys.pypy_initial_path(srcdir) + """) + # set warning control options (if any) warn_arg = interactiveconfig.warn if warn_arg is not None: Modified: pypy/branch/fast-forward/pypy/config/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/config/autopath.py (original) +++ pypy/branch/fast-forward/pypy/config/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/fast-forward/pypy/config/pypyoption.py (original) +++ pypy/branch/fast-forward/pypy/config/pypyoption.py Thu Jun 24 18:00:01 2010 @@ -8,7 +8,8 @@ modulepath = py.path.local(__file__).dirpath().dirpath().join("module") all_modules = [p.basename for p in modulepath.listdir() if p.check(dir=True, dotfile=False) - and p.join('__init__.py').check()] + and p.join('__init__.py').check() + and not p.basename.startswith('test')] essential_modules = dict.fromkeys( ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"] Modified: pypy/branch/fast-forward/pypy/conftest.py ============================================================================== --- pypy/branch/fast-forward/pypy/conftest.py (original) +++ pypy/branch/fast-forward/pypy/conftest.py Thu Jun 24 18:00:01 2010 @@ -10,11 +10,9 @@ # pytest settings pytest_plugins = "resultlog", -rsyncdirs = ['.', '../lib-python', '../demo'] +rsyncdirs = ['.', '../lib-python', '../lib_pypy', '../demo'] rsyncignore = ['_cache'] -collect_ignore = ['./lib/py'] - # PyPy's command line extra options (these are added # to py.test's standard options) # @@ -220,8 +218,10 @@ def accept_regular_test(self): if option.runappdirect: - # only collect regular tests if we are in an 'app_test' directory - return "app_test" in self.listnames() + # only collect regular tests if we are in an 'app_test' directory, + # or in test_lib_pypy + names = self.listnames() + return "app_test" in names or "test_lib_pypy" in names else: return True @@ -232,7 +232,7 @@ return True return False - def classnamefilter(self, name): + def classnamefilter(self, name): if name.startswith('Test'): return self.accept_regular_test() if name.startswith('AppTest'): Modified: pypy/branch/fast-forward/pypy/doc/_ref.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/_ref.txt (original) +++ pypy/branch/fast-forward/pypy/doc/_ref.txt Thu Jun 24 18:00:01 2010 @@ -46,11 +46,10 @@ .. _`pypy/interpreter/astcompiler/ast.py`: ../../pypy/interpreter/astcompiler/ast.py .. _`pypy/interpreter/typedef.py`: ../../pypy/interpreter/typedef.py .. _`lib/`: -.. _`pypy/lib/`: ../../pypy/lib -.. _`lib/app_test/`: ../../pypy/lib/app_test -.. _`lib/distributed/`: ../../pypy/lib/distributed -.. _`pypy/lib/stackless.py`: ../../pypy/lib/stackless.py -.. _`pypy/lib/test2`: ../../pypy/lib/test2 +.. _`lib_pypy/`: ../../lib_pypy +.. _`lib/distributed/`: ../../lib_pypy/distributed +.. _`lib_pypy/stackless.py`: ../../lib_pypy/stackless.py +.. _`lib_pypy/pypy_test/`: ../../lib_pypy/pypy_test .. _`module/`: .. _`pypy/module`: .. _`pypy/module/`: ../../pypy/module Modified: pypy/branch/fast-forward/pypy/doc/coding-guide.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/coding-guide.txt (original) +++ pypy/branch/fast-forward/pypy/doc/coding-guide.txt Thu Jun 24 18:00:01 2010 @@ -631,7 +631,7 @@ because they rely on implementation details of CPython. If we don't just modify an original CPython module but need to rewrite -it from scratch we put it into `pypy/lib/`_ as a pure application level +it from scratch we put it into `lib_pypy/`_ as a pure application level module. When we need access to interpreter-level objects we put the module into @@ -653,7 +653,7 @@ >>>> import operator >>>> operator.__file__ - '/home/hpk/pypy-dist/pypy/lib/operator.py' + '/home/hpk/pypy-dist/lib_pypy/operator.py' >>>> import opcode >>>> opcode.__file__ @@ -682,7 +682,7 @@ list of directories, specified in the ``PYTHONPATH`` environment variable. -*pypy/lib/* +*lib_pypy/* contains pure Python reimplementation of modules. @@ -794,14 +794,14 @@ --withoutmod-mymodule (the later being the default)) for py.py and translate.py. -Testing modules in ``pypy/lib`` +Testing modules in ``lib_pypy/`` -------------------------------- -You can go to the `pypy/lib/test2`_ directory and invoke the testing tool -("py.test" or "python ../../test_all.py") to run tests against the -pypy/lib hierarchy. Note, that tests in `pypy/lib/test2`_ are allowed +You can go to the `lib_pypy/pypy_test/`_ directory and invoke the testing tool +("py.test" or "python ../../pypy/test_all.py") to run tests against the +lib_pypy hierarchy. Note, that tests in `lib_pypy/pypy_test/`_ are allowed and encouraged to let their tests run at interpreter level although -`pypy/lib/`_ modules eventually live at PyPy's application level. +`lib_pypy/`_ modules eventually live at PyPy's application level. This allows us to quickly test our python-coded reimplementations against CPython. Modified: pypy/branch/fast-forward/pypy/doc/config/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/doc/config/autopath.py (original) +++ pypy/branch/fast-forward/pypy/doc/config/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.md5.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.md5.txt (original) +++ pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.md5.txt Thu Jun 24 18:00:01 2010 @@ -1,5 +1,5 @@ Use the built-in 'md5' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.sha.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.sha.txt (original) +++ pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.sha.txt Thu Jun 24 18:00:01 2010 @@ -1,5 +1,5 @@ Use the built-in 'sha' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.struct.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.struct.txt (original) +++ pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.struct.txt Thu Jun 24 18:00:01 2010 @@ -1,5 +1,5 @@ Use the built-in 'struct' module. This module is expected to be working and is included by default. -There is also a pure Python version in pypy/lib which is used +There is also a pure Python version in lib_pypy which is used if the built-in is disabled, but it is several orders of magnitude slower. Modified: pypy/branch/fast-forward/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/cpython_differences.txt (original) +++ pypy/branch/fast-forward/pypy/doc/cpython_differences.txt Thu Jun 24 18:00:01 2010 @@ -71,7 +71,7 @@ _stackless * Supported by being rewritten in pure Python (possibly using ``ctypes``): - see the `pypy/lib/`_ directory. Examples of modules that we + see the `lib_pypy/`_ directory. Examples of modules that we support this way: ``ctypes``, ``array``, ``cPickle``, ``cStringIO``, ``cmath``, ``dbm`` (?), ``datetime``, ``binascii``... Note that some modules are both in there and in the list above; @@ -79,7 +79,7 @@ at translation time). The extension modules (i.e. modules written in C, in the standard CPython) -that are neither mentioned above nor in `pypy/lib/`_ are not available in PyPy. +that are neither mentioned above nor in `lib_pypy/`_ are not available in PyPy. .. the nonstandard modules are listed below... .. _`__pypy__`: __pypy__-module.html Modified: pypy/branch/fast-forward/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/fast-forward/pypy/doc/ctypes-implementation.txt Thu Jun 24 18:00:01 2010 @@ -48,9 +48,9 @@ High-level parts ================= -The reused ``ctypes`` package lives in ``pypy/lib/ctypes``. ``_ctypes`` +The reused ``ctypes`` package lives in ``lib_pypy/ctypes``. ``_ctypes`` implementing the same interface as ``_ctypes`` in CPython is in -``pypy/lib/_ctypes``. +``lib_pypy/_ctypes``. Discussion and limitations ============================= @@ -123,8 +123,8 @@ To run the tests then:: - $ cd ../.. # back to pypy/ - $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests + $ cd ../../.. # back to pypy-trunk + $ ./pypy/translator/goal/pypy-c pypy/test_all.py lib/pypy1.2/lib_pypy/pypy_test/ctypes_tests There should be 36 skipped tests and all other tests should pass. Modified: pypy/branch/fast-forward/pypy/doc/docindex.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/docindex.txt (original) +++ pypy/branch/fast-forward/pypy/doc/docindex.txt Thu Jun 24 18:00:01 2010 @@ -207,13 +207,6 @@ `interpreter/astcompiler/`_ interpreter-level bytecode compiler, via an AST representation -`lib/`_ PyPy's wholesale reimplementations of CPython modules_ - and experimental new application-level modules - -`lib/app_test/`_ tests for the reimplementations, running on top of CPython - -`lib/distributed/`_ distributed execution prototype, based on `transparent proxies`_ - `module/`_ contains `mixed modules`_ implementing core modules with both application and interpreter level code. Not all are finished and working. Use the ``--withmod-xxx`` Modified: pypy/branch/fast-forward/pypy/doc/getting-started-python.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/getting-started-python.txt (original) +++ pypy/branch/fast-forward/pypy/doc/getting-started-python.txt Thu Jun 24 18:00:01 2010 @@ -207,18 +207,18 @@ For installation purposes, note that the executable needs to be able to find its version of the Python standard library in the following three directories: ``lib-python/2.5.2``, ``lib-python/modified-2.5.2`` and -``pypy/lib``. They are located by "looking around" starting from the +``lib_pypy``. They are located by "looking around" starting from the directory in which the executable resides. The current logic is to try to find a ``PREFIX`` from which the directories ``PREFIX/lib-python/2.5.2`` and ``PREFIX/lib-python/modified.2.5.2`` and -``PREFIX/pypy/lib`` can all be found. The prefixes that are tried are:: +``PREFIX/lib_pypy`` can all be found. The prefixes that are tried are:: . - ./share/pypy-1.2 + ./lib/pypy1.2 .. - ../share/pypy-1.2 + ../lib/pypy1.2 ../.. - ../../share/pypy-1.2 + ../../lib/pypy-1.2 ../../.. etc. Modified: pypy/branch/fast-forward/pypy/doc/maemo.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/maemo.txt (original) +++ pypy/branch/fast-forward/pypy/doc/maemo.txt Thu Jun 24 18:00:01 2010 @@ -157,11 +157,11 @@ You can just copy your whole pypy-trunk directory over to your mobile device - however, only these should be needed:: - pypy/lib - lib-python + lib/pypy1.2/lib_pypy + lib/pypy1.2/lib-python pypy/translator/goal/pypy-c -It is neccessary that the ``pypy-c`` can find a "lib-python" and "pypy/lib" directory +It is neccessary that the ``pypy-c`` can find a "lib-python" and "lib_pypy" directory if you want to successfully startup the interpreter on the device. Start ``pypy-c`` on the device. If you see an error like "setupterm: could not find terminal" Modified: pypy/branch/fast-forward/pypy/doc/objspace-proxies.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/objspace-proxies.txt (original) +++ pypy/branch/fast-forward/pypy/doc/objspace-proxies.txt Thu Jun 24 18:00:01 2010 @@ -610,7 +610,7 @@ .. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py .. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py .. _`transparent.py`: ../../pypy/objspace/std/transparent.py -.. _`tputil.py`: ../../pypy/lib/tputil.py +.. _`tputil.py`: ../../lib_pypy/tputil.py .. [D12.1] `High-Level Backends and Interpreter Feature Prototypes`, PyPy EU-Report, 2007, http://codespeak.net/pypy/extradoc/eu-report/D12.1_H-L-Backends_and_Feature_Prototypes-2007-03-22.pdf Modified: pypy/branch/fast-forward/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/release-1.3.0.txt (original) +++ pypy/branch/fast-forward/pypy/doc/release-1.3.0.txt Thu Jun 24 18:00:01 2010 @@ -5,20 +5,37 @@ Hello. We're please to announce release of PyPy 1.3. This release has two major -points. First of all, we stabilized the JIT compiler since 1.2 release, -answered user issues, fixed bugs and generally improved speed. +improvements. First of all, we stabilized the JIT compiler since 1.2 release, +answered user issues, fixed bugs, and generally improved speed. -The other point is that we're pleased to announce alpha support for loading -CPython extension modules written in C. While the main point of the release -is increased stability, this part is in alpha stage and it is not yet suited -for production environments. +We're also pleased to announce alpha support for loading CPython extension +modules written in C. While the main purpose of this release is increased +stability, this feature is in alpha stage and it is not yet suited for +production environments. Highlight of this release ========================= -XXX a rough list -- cpyext (some details, in particular: the extension module must be - recompiled, and typically "bug-fixed" w.r.t. refcounting) -- bugfixes -- blackhole-improvements -- minor jit improvements +* We introduced support for CPython extension modules written in C. As of now, + this support is in alpha, and it's very unlikely unaltered C extensions will + work out of the box, due to missing functions or refcounting details. The + support is disable by default, so you have to do:: + + import cpyext + + before trying to import any .so file. Also, libraries are source-compatible + and not binary-compatible. That means you need to recompile binaries, using + for example:: + + python setup.py build + + Details may vary, depending on your build system. Make sure you include + the above line at the beginning of setup.py or put it in your PYTHONSTARTUP. + + This is alpha feature. It'll likely segfault. You have been warned! + +* JIT bugfixes. A lot of bugs reported for the JIT have been fixed, and its + stability greatly improved since 1.2 release. + +* Various small improvements have been added to the JIT code, as well as a great + speedup of compiling time. Modified: pypy/branch/fast-forward/pypy/doc/sandbox.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/sandbox.txt (original) +++ pypy/branch/fast-forward/pypy/doc/sandbox.txt Thu Jun 24 18:00:01 2010 @@ -72,7 +72,8 @@ should do. I've successfully tried it on the JS interpreter. The controller is only called "pypy_interact" because it emulates a file hierarchy that makes pypy-c-sandbox happy - it contains (read-only) -virtual directories like /bin/lib-python and /bin/pypy/lib and it +virtual directories like /bin/lib/pypy1.2/lib-python and +/bin/lib/pypy1.2/lib_pypy and it pretends that the executable is /bin/pypy-c. Howto Modified: pypy/branch/fast-forward/pypy/doc/stackless.txt ============================================================================== --- pypy/branch/fast-forward/pypy/doc/stackless.txt (original) +++ pypy/branch/fast-forward/pypy/doc/stackless.txt Thu Jun 24 18:00:01 2010 @@ -181,7 +181,7 @@ website. Note that Tasklets and Channels are implemented at application-level in -`pypy/lib/stackless.py`_ on top of coroutines_. You can refer to this +`lib_pypy/stackless.py`_ on top of coroutines_. You can refer to this module for more details and API documentation. The stackless.py code tries to resemble the stackless C code as much Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Thu Jun 24 18:00:01 2010 @@ -385,6 +385,7 @@ def get_builtinmodule_to_install(self): """NOT_RPYTHON""" + from pypy.tool.lib_pypy import LIB_PYPY try: return self._builtinmodule_list except AttributeError: @@ -404,9 +405,7 @@ if not self.config.objspace.nofaking: for modname in self.ALL_BUILTIN_MODULES: - if not (os.path.exists( - os.path.join(os.path.dirname(pypy.__file__), - 'lib', modname+'.py'))): + if not LIB_PYPY.join(modname+'.py').check(file=True): modules.append('faked+'+modname) self._builtinmodule_list = modules Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_module.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_module.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_module.py Thu Jun 24 18:00:01 2010 @@ -54,11 +54,11 @@ r = repr(sys) assert r == "" - import _pypy_interact # known to be in pypy/lib + import _pypy_interact # known to be in lib_pypy r = repr(_pypy_interact) assert (r.startswith("')) nofile = type(_pypy_interact)('nofile', 'foo') assert repr(nofile) == "" Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_objspace.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_objspace.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_objspace.py Thu Jun 24 18:00:01 2010 @@ -259,3 +259,23 @@ def test_sys_import(self): from pypy.interpreter.main import run_string run_string('import sys', space=self.space) + + def test_get_builtinmodule_to_install(self): + space = self.space + try: + # force rebuilding with this fake builtin + space.ALL_BUILTIN_MODULES.append('this_doesnt_exist') + del space._builtinmodule_list + mods = space.get_builtinmodule_to_install() + + assert '__pypy__' in mods # real builtin + assert 'array' not in mods # in lib_pypy + assert 'faked+array' not in mods # in lib_pypy + assert 'this_doesnt_exist' not in mods # not in lib_pypy + assert 'faked+this_doesnt_exist' in mods # not in lib_pypy, but in + # ALL_BUILTIN_MODULES + finally: + # rebuild the original list + space.ALL_BUILTIN_MODULES.pop() + del space._builtinmodule_list + mods = space.get_builtinmodule_to_install() Modified: pypy/branch/fast-forward/pypy/jit/backend/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/tool/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/backend/x86/tool/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/backend/x86/tool/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/jit/tl/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/jit/tl/spli/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tl/spli/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/tl/spli/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/jit/tool/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/jit/tool/autopath.py (original) +++ pypy/branch/fast-forward/pypy/jit/tool/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/module/_codecs/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_codecs/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/module/_codecs/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/module/_sre/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/_sre/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/module/_sre/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/module/cpyext/api.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/api.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/api.py Thu Jun 24 18:00:01 2010 @@ -809,7 +809,6 @@ kwds["includes"] = ['Python.h'] # this is our Python.h # Generate definitions for global structures - struct_file = udir.join('pypy_structs.c') structs = ["#include "] for name, (typ, expr) in GLOBALS.iteritems(): if name.endswith('#'): @@ -819,7 +818,7 @@ structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name)) elif typ == 'PyDateTime_CAPI*': structs.append('%s %s = NULL;' % (typ, name)) - struct_file.write('\n'.join(structs)) + struct_source = '\n'.join(structs) eci = ExternalCompilationInfo( include_dirs=include_dirs, @@ -833,9 +832,8 @@ source_dir / "bufferobject.c", source_dir / "object.c", source_dir / "cobject.c", - struct_file, ], - separate_module_sources = [code], + separate_module_sources = [code, struct_source], export_symbols=export_symbols_eci, compile_extra=compile_extra, **kwds Modified: pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py (original) +++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py Thu Jun 24 18:00:01 2010 @@ -15,7 +15,7 @@ from pypy.module.cpyext.pyobject import RefcountState from pypy.module.cpyext.pyobject import Py_DecRef, InvalidPointerException from pypy.translator.goal import autopath -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): @@ -160,7 +160,8 @@ kwds["compile_extra"] = ["/we4013"] else: kwds["link_files"] = [str(api_library + '.so')] - kwds["compile_extra"] = ["-Werror=implicit-function-declaration"] + if sys.platform == 'linux2': + kwds["compile_extra"]=["-Werror=implicit-function-declaration"] return compile_module(name, **kwds) Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Thu Jun 24 18:00:01 2010 @@ -31,9 +31,8 @@ 'stderr' : 'state.getio(space).w_stderr', '__stderr__' : 'state.getio(space).w_stderr', 'pypy_objspaceclass' : 'space.wrap(repr(space))', - #'pypy_prefix': added by pypy_initial_path() when it succeeds, pointing - # to the trunk of a checkout or to the dir /usr/share/pypy-1.1 . - + #'prefix' : # added by pypy_initial_path() when it + #'exec_prefix' : # succeeds, pointing to trunk or /usr 'path' : 'state.get(space).w_path', 'modules' : 'state.get(space).w_modules', 'argv' : 'state.get(space).w_argv', @@ -99,11 +98,8 @@ if space.config.translating and not we_are_translated(): # don't get the filesystemencoding at translation time assert self.filesystemencoding is None - else: - from pypy.module.sys.interp_encoding import _getfilesystemencoding - self.filesystemencoding = _getfilesystemencoding(space) - def getmodule(self, name): + def getmodule(self, name): space = self.space w_modules = self.get('modules') try: Modified: pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/interp_encoding.py Thu Jun 24 18:00:01 2010 @@ -55,4 +55,6 @@ """Return the encoding used to convert Unicode filenames in operating system filenames. """ + if space.sys.filesystemencoding is None: + space.sys.filesystemencoding = _getfilesystemencoding(space) return space.wrap(space.sys.filesystemencoding) Modified: pypy/branch/fast-forward/pypy/module/sys/state.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/state.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/state.py Thu Jun 24 18:00:01 2010 @@ -4,7 +4,6 @@ import pypy from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace -from pypy.module.sys import version import sys, os, stat, errno @@ -33,22 +32,34 @@ if not stat.S_ISDIR(st[0]): raise OSError(errno.ENOTDIR, path) -def getinitialpath(srcdir): - # build the initial path from the srcdir, which is the path of - # the "dist" directory of a PyPy checkout. - lib_python = os.path.join(srcdir, 'lib-python') - dirname = version.CPYTHON_VERSION_DIR - +def getinitialpath(prefix): + from pypy.module.sys.version import PYPY_VERSION + libdir = os.path.join(prefix, 'lib') + pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) + # search for the stdlib both in $PREFIX/lib/pypy1.2 and $PREFIX + for lib_prefix in [pypyxy_dir, prefix]: + try: + return get_importlist(lib_prefix) + except OSError: + pass + raise OSError # stdlib not foud + +def get_importlist(lib_prefix): + from pypy.module.sys.version import CPYTHON_VERSION + dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], + CPYTHON_VERSION[1], + CPYTHON_VERSION[2]) + lib_python = os.path.join(lib_prefix, 'lib-python') python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) checkdir(python_std_lib_modified) - pypydir = os.path.join(srcdir, 'pypy') - pypy_lib = os.path.join(pypydir, 'lib') - checkdir(pypy_lib) + + lib_pypy = os.path.join(lib_prefix, 'lib_pypy') + checkdir(lib_pypy) importlist = [] - importlist.append(pypy_lib) + importlist.append(lib_pypy) importlist.append(python_std_lib_modified) importlist.append(python_std_lib) return importlist @@ -59,7 +70,9 @@ except OSError: return space.w_None else: - space.setitem(space.sys.w_dict, space.wrap('pypy_prefix'), + space.setitem(space.sys.w_dict, space.wrap('prefix'), + space.wrap(srcdir)) + space.setitem(space.sys.w_dict, space.wrap('exec_prefix'), space.wrap(srcdir)) return space.newlist([space.wrap(p) for p in path]) Modified: pypy/branch/fast-forward/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/module/sys/version.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/sys/version.py (original) +++ pypy/branch/fast-forward/pypy/module/sys/version.py Thu Jun 24 18:00:01 2010 @@ -4,13 +4,10 @@ import os -CPYTHON_VERSION = (2, 7, 0, "beta", 42) +CPYTHON_VERSION = (2, 7, 0, "final", 42) CPYTHON_API_VERSION = 1012 -CPYTHON_VERSION_DIR = '%d.%d.%d' % (CPYTHON_VERSION[0], - CPYTHON_VERSION[1], - CPYTHON_VERSION[2]) - +# when changing the pypy version, remind to also change the name of trunk/lib/pypyX.Y PYPY_VERSION = (1, 2, 0, "beta", '?') # the last item is replaced by the svn revision ^^^ Modified: pypy/branch/fast-forward/pypy/objspace/flow/model.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/flow/model.py (original) +++ pypy/branch/fast-forward/pypy/objspace/flow/model.py Thu Jun 24 18:00:01 2010 @@ -7,7 +7,7 @@ from pypy.tool.uid import uid, Hashable from pypy.tool.descriptor import roproperty from pypy.tool.sourcetools import PY_IDENTIFIER, nice_repr_for_func -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict """ memory size before and after introduction of __slots__ Modified: pypy/branch/fast-forward/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/floatobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/floatobject.py Thu Jun 24 18:00:01 2010 @@ -77,23 +77,34 @@ def float_w__Float(space, w_float): return w_float.floatval -def should_not_look_like_an_int(s): - for c in s: - if c in '.eE': - break +def float2string(space, w_float, format): + x = w_float.floatval + # we special-case explicitly inf and nan here + if isinf(x): + if x > 0.0: + s = "inf" + else: + s = "-inf" + elif isnan(x): + s = "nan" else: - s += '.0' - return s + s = formatd(format, x) + # We want float numbers to be recognizable as such, + # i.e., they should contain a decimal point or an exponent. + # However, %g may print the number as an integer; + # in such cases, we append ".0" to the string. + for c in s: + if c in '.eE': + break + else: + s += '.0' + return space.wrap(s) def repr__Float(space, w_float): - x = w_float.floatval - s = formatd("%.17g", x) - return space.wrap(should_not_look_like_an_int(s)) + return float2string(space, w_float, "%.17g") def str__Float(space, w_float): - x = w_float.floatval - s = formatd("%.12g", x) - return space.wrap(should_not_look_like_an_int(s)) + return float2string(space, w_float, "%.12g") # ____________________________________________________________ # A mess to handle all cases of float comparison without relying Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_floatobject.py Thu Jun 24 18:00:01 2010 @@ -95,7 +95,14 @@ inf = 1e200*1e200 assert float("inf") == inf assert float("-INf") == -inf - assert 'nan' in str(float("-nAn")).lower() + assert str(inf) == "inf" + assert str(-inf) == "-inf" + assert str(float("nan")) == "nan" + assert str(float("-nAn")) == "nan" + assert repr(inf) == "inf" + assert repr(-inf) == "-inf" + assert repr(float("nan")) == "nan" + assert repr(float("-nAn")) == "nan" def test_float_unicode(self): # u00A0 and u2000 are some kind of spaces Modified: pypy/branch/fast-forward/pypy/pytest-A.cfg ============================================================================== --- pypy/branch/fast-forward/pypy/pytest-A.cfg (original) +++ pypy/branch/fast-forward/pypy/pytest-A.cfg Thu Jun 24 18:00:01 2010 @@ -1,4 +1,4 @@ -cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module', 'lib'] +cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module'] interp = ['translator/goal/pypy-c'] test_driver = ['test_all.py', '-A'] Modified: pypy/branch/fast-forward/pypy/rlib/parsing/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/parsing/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/rlib/parsing/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/rlib/rmd5.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rmd5.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rmd5.py Thu Jun 24 18:00:01 2010 @@ -2,7 +2,7 @@ """ RPython implementation of MD5 checksums. -See also the pure Python implementation in pypy/lib/md5.py, which might +See also the pure Python implementation in lib_pypy/md5.py, which might or might not be faster than this one on top of CPython. This is an implementation of the MD5 hash function, Modified: pypy/branch/fast-forward/pypy/rlib/rsdl/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rsdl/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rsdl/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/rlib/rsha.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rsha.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rsha.py Thu Jun 24 18:00:01 2010 @@ -2,7 +2,7 @@ """A sample implementation of SHA-1 in RPython. - See also the pure Python implementation in pypy/lib/sha.py, which might + See also the pure Python implementation in lib_pypy/sha.py, which might or might not be faster than this one on top of CPython. Framework adapted from Dinu Gherman's MD5 implementation by Modified: pypy/branch/fast-forward/pypy/rlib/rzipfile.py ============================================================================== --- pypy/branch/fast-forward/pypy/rlib/rzipfile.py (original) +++ pypy/branch/fast-forward/pypy/rlib/rzipfile.py Thu Jun 24 18:00:01 2010 @@ -12,7 +12,8 @@ rzlib = None # XXX hack to get crc32 to work -from pypy.lib.binascii import crc_32_tab +from pypy.tool.lib_pypy import import_from_lib_pypy +crc_32_tab = import_from_lib_pypy('binascii').crc_32_tab rcrc_32_tab = [r_uint(i) for i in crc_32_tab] Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lltype.py Thu Jun 24 18:00:01 2010 @@ -9,7 +9,7 @@ from pypy.rlib.objectmodel import Symbolic from pypy.tool.uid import Hashable from pypy.tool.tls import tlsobject -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict from types import NoneType from sys import maxint import weakref Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/rclass.py Thu Jun 24 18:00:01 2010 @@ -21,7 +21,7 @@ from pypy.annotation import model as annmodel from pypy.rlib.rarithmetic import intmask from pypy.rlib import objectmodel -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict from pypy.rpython.lltypesystem.lloperation import llop # Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_lltype.py Thu Jun 24 18:00:01 2010 @@ -1,7 +1,7 @@ import py from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.lltypesystem import lltype, rffi -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict def isweak(p, T): try: Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py Thu Jun 24 18:00:01 2010 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.debug import ll_assert -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class GCData(object): Modified: pypy/branch/fast-forward/pypy/rpython/microbench/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/microbench/autopath.py (original) +++ pypy/branch/fast-forward/pypy/rpython/microbench/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/fast-forward/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/fast-forward/pypy/rpython/ootypesystem/rclass.py Thu Jun 24 18:00:01 2010 @@ -10,7 +10,7 @@ from pypy.rpython.exceptiondata import standardexceptions from pypy.tool.pairtype import pairtype from pypy.tool.sourcetools import func_with_new_name -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict OBJECT = ootype.ROOT META = ootype.Instance("Meta", ootype.ROOT, Modified: pypy/branch/fast-forward/pypy/tool/algo/graphlib.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/algo/graphlib.py (original) +++ pypy/branch/fast-forward/pypy/tool/algo/graphlib.py Thu Jun 24 18:00:01 2010 @@ -6,7 +6,7 @@ 'edges' is a dict mapping vertices to a list of edges with its source. Note that we can usually use 'edges' as the set of 'vertices' too. """ -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class Edge: Modified: pypy/branch/fast-forward/pypy/tool/algo/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/algo/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/tool/algo/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/tool/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/autopath.py (original) +++ pypy/branch/fast-forward/pypy/tool/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/tool/compat.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/compat.py (original) +++ pypy/branch/fast-forward/pypy/tool/compat.py Thu Jun 24 18:00:01 2010 @@ -6,5 +6,8 @@ try: from md5 import md5 except ImportError: - # no _md5 module on this platform - from pypy.lib.md5 import md5 + # no _md5 module on this platform. Try hard to find a pure-python one + # by fishing it from lib_pypy + from pypy.tool.lib_pypy import import_from_lib_pypy + md5 = import_from_lib_pypy('md5') + del import_from_lib_pypy Modified: pypy/branch/fast-forward/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/autopath.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/tool/pytest/confpath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/pytest/confpath.py (original) +++ pypy/branch/fast-forward/pypy/tool/pytest/confpath.py Thu Jun 24 18:00:01 2010 @@ -1,12 +1,12 @@ import autopath import py import pypy -from pypy.module.sys.version import CPYTHON_VERSION_DIR +from pypy.tool import lib_pypy pypydir = py.path.local(pypy.__file__).dirpath() distdir = pypydir.dirpath() testresultdir = distdir.join('testresult') assert pypydir.check(dir=1) -libpythondir = distdir.join('lib-python') -regrtestdir = libpythondir.join(CPYTHON_VERSION_DIR, 'test') -modregrtestdir = libpythondir.join('modified-' + CPYTHON_VERSION_DIR, 'test') +libpythondir = lib_pypy.LIB_PYTHON +regrtestdir = lib_pypy.LIB_PYTHON_VANILLA.join('test') +modregrtestdir = lib_pypy.LIB_PYTHON_MODIFIED.join('test') Modified: pypy/branch/fast-forward/pypy/tool/release/package.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/release/package.py (original) +++ pypy/branch/fast-forward/pypy/tool/release/package.py Thu Jun 24 18:00:01 2010 @@ -46,14 +46,13 @@ raise PyPyCNotFound('Please compile pypy first, using translate.py') builddir = udir.ensure("build", dir=True) pypydir = builddir.ensure(name, dir=True) + # Careful: to copy lib_pypy, copying just the svn-tracked files + # would not be enough: there are also ctypes_config_cache/_*_cache.py. shutil.copytree(str(basedir.join('lib-python')), str(pypydir.join('lib-python')), - ignore=ignore_patterns('.svn', '*.pyc', '*~')) - # Careful: to copy pypy/lib, copying just the svn-tracked files - # would not be enough: there are also ctypes_config_cache/_*_cache.py. - pypydir.ensure('pypy', dir=True) - shutil.copytree(str(basedir.join('pypy', 'lib')), - str(pypydir.join('pypy', 'lib')), + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + shutil.copytree(str(basedir.join('lib_pypy')), + str(pypydir.join('lib_pypy')), ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) Modified: pypy/branch/fast-forward/pypy/tool/release/test/test_package.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/release/test/test_package.py (original) +++ pypy/branch/fast-forward/pypy/tool/release/test/test_package.py Thu Jun 24 18:00:01 2010 @@ -2,6 +2,7 @@ import py from pypy.tool.autopath import pypydir from pypy.tool.release.package import package +from pypy.module.sys.version import CPYTHON_VERSION import tarfile, os def test_dir_structure(): @@ -14,15 +15,17 @@ fake_pypy_c = False try: builddir = package(py.path.local(pypydir).dirpath(), 'test') - assert builddir.join('test', 'lib-python', '2.5.2', 'test').check() - assert builddir.join('test', 'bin', 'pypy-c').check() - assert builddir.join('test', 'pypy', 'lib', 'syslog.py').check() - assert not builddir.join('test', 'pypy', 'lib', 'py').check() - assert not builddir.join('test', 'pypy', 'lib', 'ctypes_configure').check() - assert builddir.join('test', 'LICENSE').check() - assert builddir.join('test', 'README').check() + prefix = builddir.join('test') + cpyver = '%d.%d.%d' % CPYTHON_VERSION[:3] + assert prefix.join('lib-python', cpyver, 'test').check() + assert prefix.join('bin', 'pypy-c').check() + assert prefix.join('lib_pypy', 'syslog.py').check() + assert not prefix.join('lib_pypy', 'py').check() + assert not prefix.join('lib_pypy', 'ctypes_configure').check() + assert prefix.join('LICENSE').check() + assert prefix.join('README').check() th = tarfile.open(str(builddir.join('test.tar.bz2'))) - assert th.getmember('test/pypy/lib/syslog.py') + assert th.getmember('test/lib_pypy/syslog.py') finally: if fake_pypy_c: pypy_c.remove() Modified: pypy/branch/fast-forward/pypy/tool/stdlib___future__.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/stdlib___future__.py (original) +++ pypy/branch/fast-forward/pypy/tool/stdlib___future__.py Thu Jun 24 18:00:01 2010 @@ -1,10 +1,8 @@ # load __future__.py constants def load_module(): - import py - from pypy.module.sys.version import CPYTHON_VERSION_DIR - to_future = "lib-python/%s/__future__.py" % (CPYTHON_VERSION_DIR,) - module_path = py.path.local(__file__).dirpath().dirpath().dirpath(to_future) + from pypy.tool.lib_pypy import LIB_PYTHON_VANILLA + module_path = LIB_PYTHON_VANILLA.join('__future__.py') execfile(str(module_path), globals()) load_module() Modified: pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py (original) +++ pypy/branch/fast-forward/pypy/tool/stdlib_opcode.py Thu Jun 24 18:00:01 2010 @@ -4,8 +4,6 @@ (module attributes with the `host_` prefix). """ -from pypy.module.sys.version import CPYTHON_VERSION_DIR - # load opcode.py as pythonopcode from our own lib __all__ = ['opmap', 'opname', 'HAVE_ARGUMENT', @@ -108,9 +106,8 @@ opmap as host_opmap, HAVE_ARGUMENT as host_HAVE_ARGUMENT) def load_pypy_opcode(): - import py - lib_python = 'lib-python/modified-%s/opcode.py' % (CPYTHON_VERSION_DIR,) - opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath(lib_python) + from pypy.tool.lib_pypy import LIB_PYTHON_MODIFIED + opcode_path = LIB_PYTHON_MODIFIED.join('opcode.py') d = {} execfile(str(opcode_path), d) for name in __all__: Modified: pypy/branch/fast-forward/pypy/tool/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/tool/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/tool/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/backendopt/test/test_mallocprediction.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/backendopt/test/test_mallocprediction.py (original) +++ pypy/branch/fast-forward/pypy/translator/backendopt/test/test_mallocprediction.py Thu Jun 24 18:00:01 2010 @@ -169,7 +169,7 @@ t, graph = rtype(entrypoint, [int]) total0 = preparation(t, t.graphs, heuristic=heuristic) total = clever_inlining_and_malloc_removal(t) - assert total0 + total == 10 + assert total0 + total == 16 def test_richards(): from pypy.translator.goal.richards import entry_point Modified: pypy/branch/fast-forward/pypy/translator/benchmark/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/benchmark/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/benchmark/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/c/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/c/database.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/database.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/database.py Thu Jun 24 18:00:01 2010 @@ -16,7 +16,7 @@ from pypy.translator.c.extfunc import do_the_getting from pypy import conftest from pypy.translator.c import gc -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class NoCorrespondingNode(Exception): Modified: pypy/branch/fast-forward/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/funcgen.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/funcgen.py Thu Jun 24 18:00:01 2010 @@ -13,7 +13,7 @@ from pypy.rpython.lltypesystem.llmemory import Address from pypy.translator.backendopt.ssa import SSI_to_SSA from pypy.translator.backendopt.innerloop import find_inner_loops -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict PyObjPtr = Ptr(PyObject) Modified: pypy/branch/fast-forward/pypy/translator/c/gcc/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/gcc/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/c/gcc/autopath.py Thu Jun 24 18:00:01 2010 @@ -37,8 +37,7 @@ partdir = head head, tail = os.path.split(head) if tail == part: - # check if "../py/__init__.py" exists - checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') if not os.path.exists(checkfile): error = "Cannot find %r" % (os.path.normpath(checkfile),) break @@ -127,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/c/src/support.h ============================================================================== --- pypy/branch/fast-forward/pypy/translator/c/src/support.h (original) +++ pypy/branch/fast-forward/pypy/translator/c/src/support.h Thu Jun 24 18:00:01 2010 @@ -26,7 +26,7 @@ PyString_FromStringAndSize(_RPyString_AsString(rpystr), RPyString_Size(rpystr)) #define PyUnicode_FromRPyUnicode(rpystr) \ - PyUnicode_FromUnicode(_RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) + _PyUnicode_FromRPyUnicode(_RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) #define PyString_ToRPyString(s, rpystr) \ memcpy(_RPyString_AsString(rpystr), PyString_AS_STRING(s), \ @@ -128,6 +128,7 @@ PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index); int PyTuple_SetItem_WithIncref(PyObject *tuple, int index, PyObject *o); int PySequence_Contains_with_exc(PyObject *seq, PyObject *ob); +PyObject* _PyUnicode_FromRPyUnicode(wchar_t *items, long length); /* implementations */ @@ -501,6 +502,17 @@ return ret; } +PyObject* _PyUnicode_FromRPyUnicode(wchar_t *items, long length) +{ + PyObject *u = PyUnicode_FromUnicode(NULL, length); + long i; + for (i=0; i> sys.stderr, ('debug: WARNING: library path not found, ' + 'using compiled-in sys.path') + newpath = sys.path[:] + break + newpath = sys.pypy_initial_path(dirname) + if newpath is None: + search = dirname # walk to the parent directory + continue + break # found! + return newpath def setup_initial_paths(executable, nanos): # a substituted os if we are translated global os os = nanos - AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d' # find the full path to the executable, assuming that if there is no '/' # in the provided one then we must look along the $PATH if we_are_translated() and IS_WINDOWS and not executable.lower().endswith('.exe'): @@ -204,24 +219,7 @@ break sys.executable = os.path.abspath(executable) - # set up a sys.path that depends on the local machine - autosubpath = AUTOSUBPATH % sys.pypy_version_info[:2] - search = executable - while 1: - dirname = resolvedirof(search) - if dirname == search: - # not found! let's hope that the compiled-in path is ok - print >> sys.stderr, ('debug: WARNING: library path not found, ' - 'using compiled-in sys.path') - newpath = sys.path[:] - break - newpath = sys.pypy_initial_path(dirname) - if newpath is None: - newpath = sys.pypy_initial_path(os.path.join(dirname, autosubpath)) - if newpath is None: - search = dirname # walk to the parent directory - continue - break # found! + newpath = get_library_path(executable) path = os.getenv('PYTHONPATH') if path: newpath = path.split(os.pathsep) + newpath Modified: pypy/branch/fast-forward/pypy/translator/goal/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/targetpypystandalone.py Thu Jun 24 18:00:01 2010 @@ -225,7 +225,8 @@ return PyPyJitPolicy() def get_entry_point(self, config): - from pypy.lib.ctypes_config_cache import rebuild + from pypy.tool.lib_pypy import import_from_lib_pypy + rebuild = import_from_lib_pypy('ctypes_config_cache/rebuild') rebuild.try_rebuild() space = make_objspace(config) Modified: pypy/branch/fast-forward/pypy/translator/goal/test2/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/test2/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/test2/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py Thu Jun 24 18:00:01 2010 @@ -486,3 +486,59 @@ data = child_out_err.read(11) assert data == '\x00(STDOUT)\n\x00' # from stdout child_out_err.close() + + +class AppTestAppMain: + + def setup_class(self): + # ------------------------------------ + # setup code for test_get_library_path + # ------------------------------------ + from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION + libroot = 'lib/pypy%d.%d' % PYPY_VERSION[:2] + cpy_ver = '%d.%d.%d' % CPYTHON_VERSION[:3] + + goal_dir = os.path.dirname(app_main) + # build a directory hierarchy like which contains both bin/pypy-c and + # lib/pypy1.2/* + prefix = udir.join('pathtest') + fake_exe = prefix.join('bin/pypy-c').ensure(file=1) + pypyxy = prefix.join(libroot).ensure(dir=1) + expected_path = [str(pypyxy.join(subdir).ensure(dir=1)) + for subdir in ('lib_pypy', + 'lib-python/modified-%s' % cpy_ver, + 'lib-python/%s' % cpy_ver)] + + self.w_goal_dir = self.space.wrap(goal_dir) + self.w_fake_exe = self.space.wrap(str(fake_exe)) + self.w_expected_path = self.space.wrap(expected_path) + self.w_trunkdir = self.space.wrap(os.path.dirname(autopath.pypydir)) + + def test_get_library_path(self): + import sys + import os + sys.path.append(self.goal_dir) + try: + import app_main + app_main.os = os + newpath = app_main.get_library_path('/tmp/pypy-c') # stdlib not found + assert newpath == sys.path + newpath = app_main.get_library_path(self.fake_exe) + assert newpath == self.expected_path + finally: + sys.path.pop() + + def test_trunk_can_be_prefix(self): + import sys + import os + sys.path.append(self.goal_dir) + try: + import app_main + app_main.os = os + pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c') + newpath = app_main.get_library_path(pypy_c) + assert len(newpath) == 3 + for p in newpath: + assert p.startswith(self.trunkdir) + finally: + sys.path.pop() Modified: pypy/branch/fast-forward/pypy/translator/microbench/pybench/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/microbench/pybench/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/microbench/pybench/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/oosupport/function.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/oosupport/function.py (original) +++ pypy/branch/fast-forward/pypy/translator/oosupport/function.py Thu Jun 24 18:00:01 2010 @@ -7,7 +7,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.treebuilder import SubOperation from pypy.translator.oosupport.metavm import InstructionList, StoreResult -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict def render_sub_op(sub_op, db, generator): Modified: pypy/branch/fast-forward/pypy/translator/sandbox/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/pypy_interact.py Thu Jun 24 18:00:01 2010 @@ -26,6 +26,7 @@ from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile +from pypy.tool.lib_pypy import LIB_ROOT class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): debug = True @@ -50,17 +51,15 @@ tmpdirnode = Dir({}) else: tmpdirnode = RealDir(self.tmpdir, exclude=exclude) - pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) + libroot = str(LIB_ROOT) return Dir({ 'bin': Dir({ 'pypy-c': RealFile(self.executable), - 'lib-python': RealDir(os.path.join(pypydist, 'lib-python'), + 'lib-python': RealDir(os.path.join(libroot, 'lib-python'), + exclude=exclude), + 'lib_pypy': RealDir(os.path.join(libroot, 'lib_pypy'), exclude=exclude), - 'pypy': Dir({ - 'lib': RealDir(os.path.join(pypydist, 'pypy', 'lib'), - exclude=exclude), - }), }), 'tmp': tmpdirnode, }) Modified: pypy/branch/fast-forward/pypy/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/sandlib.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/sandlib.py Thu Jun 24 18:00:01 2010 @@ -6,7 +6,6 @@ import py import sys, os, posixpath, errno, stat, time -from pypy.lib import marshal # see below from pypy.rpython.module.ll_os_stat import s_StatResult from pypy.tool.ansi_print import AnsiLog from pypy.rlib.rarithmetic import r_longlong @@ -26,12 +25,14 @@ py.log.setconsumer("sandlib", MyAnsiLog()) -# Note: we use pypy.lib.marshal instead of the built-in marshal +# Note: we use lib_pypy/marshal.py instead of the built-in marshal # for two reasons. The built-in module could be made to segfault # or be attackable in other ways by sending malicious input to # load(). Also, marshal.load(f) blocks with the GIL held when # f is a pipe with no data immediately avaialble, preventing the # _waiting_thread to run. +from pypy.tool.lib_pypy import import_from_lib_pypy +marshal = import_from_lib_pypy('marshal') def read_message(f, timeout=None): # warning: 'timeout' is not really reliable and should only be used Modified: pypy/branch/fast-forward/pypy/translator/sandbox/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/sandbox/test/test_pypy_interact.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/sandbox/test/test_pypy_interact.py (original) +++ pypy/branch/fast-forward/pypy/translator/sandbox/test/test_pypy_interact.py Thu Jun 24 18:00:01 2010 @@ -24,7 +24,7 @@ assert_(argv[0] == '/bin/pypy-c', "bad argv[0]") st = os.lstat('/bin/pypy-c') assert_(stat.S_ISREG(st.st_mode), "bad st_mode for /bin/pypy-c") - for dirname in ['/bin/lib-python/2.5.2', '/bin/pypy/lib']: + for dirname in ['/bin/lib-python/2.5.2', '/bin/lib_pypy']: st = os.stat(dirname) assert_(stat.S_ISDIR(st.st_mode), "bad st_mode for " + dirname) assert_(os.environ.get('PYTHONPATH') is None, "unexpected $PYTHONPATH") @@ -70,7 +70,7 @@ def setup_module(mod): t = Translation(mini_pypy_like_entry_point, backend='c', - standalone=True, sandbox=True) + standalone=True, sandbox=True) mod.executable = str(t.compile()) Modified: pypy/branch/fast-forward/pypy/translator/test/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/test/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/test/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/tool/autopath.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/tool/autopath.py (original) +++ pypy/branch/fast-forward/pypy/translator/tool/autopath.py Thu Jun 24 18:00:01 2010 @@ -126,7 +126,7 @@ # set guaranteed attributes pypydir, this_dir = __dirinfo('pypy') -import py +import py # note: py is imported only AFTER the path has been set libpythondir = str(py.path.local(pypydir).dirpath().join('lib-python', '2.5.2')) libpythonmodifieddir = str(py.path.local(libpythondir).dirpath().join('modified-2.5.2')) Modified: pypy/branch/fast-forward/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/tool/lltracker.py (original) +++ pypy/branch/fast-forward/pypy/translator/tool/lltracker.py Thu Jun 24 18:00:01 2010 @@ -8,7 +8,7 @@ from pypy.rpython.memory.gcheader import header2obj from pypy.translator.tool.reftracker import BaseRefTrackerPage, MARKER from pypy.tool.uid import uid -from pypy.lib.identity_dict import identity_dict +from pypy.tool.identity_dict import identity_dict class LLRefTrackerPage(BaseRefTrackerPage): From fijal at codespeak.net Thu Jun 24 18:29:53 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jun 2010 18:29:53 +0200 (CEST) Subject: [pypy-svn] r75560 - pypy/trunk/pypy/tool/release Message-ID: <20100624162953.2A94736C22E@codespeak.net> Author: fijal Date: Thu Jun 24 18:29:51 2010 New Revision: 75560 Modified: pypy/trunk/pypy/tool/release/force-builds.py Log: Disable even that os/x, doesn't make much sense Modified: pypy/trunk/pypy/tool/release/force-builds.py ============================================================================== --- pypy/trunk/pypy/tool/release/force-builds.py (original) +++ pypy/trunk/pypy/tool/release/force-builds.py Thu Jun 24 18:29:51 2010 @@ -25,7 +25,7 @@ 'pypy-c-stackless-app-level-linux-x86-32', 'pypy-c-app-level-win-32', 'pypy-c-jit-linux-x86-32', - 'pypy-c-jit-macosx-x86-32', +# 'pypy-c-jit-macosx-x86-32', 'pypy-c-jit-win-x86-32', ] From benjamin at codespeak.net Fri Jun 25 01:18:06 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 01:18:06 +0200 (CEST) Subject: [pypy-svn] r75571 - pypy/trunk/pypy/doc/jit Message-ID: <20100624231806.8FDF7282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 01:18:03 2010 New Revision: 75571 Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt Log: a few edits Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt ============================================================================== --- pypy/trunk/pypy/doc/jit/pyjitpl5.txt (original) +++ pypy/trunk/pypy/doc/jit/pyjitpl5.txt Fri Jun 25 01:18:03 2010 @@ -8,15 +8,15 @@ Implementation of the JIT ========================= -The JIT's `theory`_ is great in principle, but actual code is a different +The JIT's `theory`_ is great in principle, the but actual code is a different story. This section tries to give a high level overview of how PyPy's JIT is -implemented. It's helpful to have a basic understanding of how the PyPy -`translation tool chain`_ works before digging into the sources. +implemented. It's helpful to have an understanding of how the PyPy `translation +tool chain`_ works before digging into the sources. -Almost all JIT specific code is found in the two pypy/jit subdirectories, -metainterp, and backend. The metainterp directory holds platform independent -code including the translation generator, the tracer, and the optimizer. Code -in the backend directory is responsible for generating machine code. +Almost all JIT specific code is found in pypy/jit subdirectories. Translation +time code is in the codewriter directory. The metainterp directory holds +platform independent code including the the tracer and the optimizer. Code in +the backend directory is responsible for generating machine code. .. _`theory`: overview.html .. _`translation tool chain`: ../translation.html @@ -34,7 +34,7 @@ interpreter defines its hints in pypy/module/pypyjit/interp_jit.py in a few overriden methods of the defaut interpreter loop. -The interpreter wishing to use the PyPy's JIT must define a list of *green* +An interpreter wishing to use the PyPy's JIT must define a list of *green* variables and a list of *red* variables. The *green* variables are loop constants. They are used to identify the current loop. Red variables are for everything else used in the execution loop. For example, the Python interpreter @@ -58,11 +58,11 @@ is replaced with a call to a function, maybe_compile_and_run in warmstate.py, that checks if current loop is "hot" and should be compiled. -Next, starting with the portal graph, metainterp/codewriter.py converts the -graphs of the interpreter into JIT bytecode. Since this bytecode is stored in -the final binary, it's designed to be concise rather than fast. The bytecode -codewriter doesn't "see" (what it sees is defined by the JIT's policy) every -part of the interpreter. In these cases, it simply inserts an opaque call. +Next, starting with the portal graph, codewriter/*.py converts the graphs of the +interpreter into JIT bytecode. Since this bytecode is stored in the final +binary, it's designed to be concise rather than fast. The bytecode codewriter +doesn't "see" (what it sees is defined by the JIT's policy) every part of the +interpreter. In these cases, it simply inserts an opaque call. Finally, translation finishes, including the bytecode of the interpreter in the final binary, and interpreter is ready to use the runtime component of the JIT. From afa at codespeak.net Fri Jun 25 08:40:58 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 08:40:58 +0200 (CEST) Subject: [pypy-svn] r75574 - pypy/trunk/pypy/doc/jit Message-ID: <20100625064058.A4846282B9C@codespeak.net> Author: afa Date: Fri Jun 25 08:40:56 2010 New Revision: 75574 Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt Log: Grammatical typo Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt ============================================================================== --- pypy/trunk/pypy/doc/jit/pyjitpl5.txt (original) +++ pypy/trunk/pypy/doc/jit/pyjitpl5.txt Fri Jun 25 08:40:56 2010 @@ -8,7 +8,7 @@ Implementation of the JIT ========================= -The JIT's `theory`_ is great in principle, the but actual code is a different +The JIT's `theory`_ is great in principle, but the actual code is a different story. This section tries to give a high level overview of how PyPy's JIT is implemented. It's helpful to have an understanding of how the PyPy `translation tool chain`_ works before digging into the sources. From hpk at codespeak.net Fri Jun 25 10:28:03 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 25 Jun 2010 10:28:03 +0200 (CEST) Subject: [pypy-svn] r75575 - pypy/trunk/py/_process Message-ID: <20100625082803.1E064282B9C@codespeak.net> Author: hpk Date: Fri Jun 25 10:28:02 2010 New Revision: 75575 Modified: pypy/trunk/py/_process/cmdexec.py Log: refine unicode handling for py.process.cmdexec Modified: pypy/trunk/py/_process/cmdexec.py ============================================================================== --- pypy/trunk/py/_process/cmdexec.py (original) +++ pypy/trunk/py/_process/cmdexec.py Fri Jun 25 10:28:02 2010 @@ -8,20 +8,25 @@ from subprocess import Popen, PIPE def cmdexec(cmd): - """ return output of executing 'cmd' in a separate process. + """ return unicode output of executing 'cmd' in a separate process. raise cmdexec.ExecutionFailed exeception if the command failed. the exception will provide an 'err' attribute containing the error-output from the command. + if the subprocess module does not provide a proper encoding/unicode strings + sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'. """ process = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.stdout.encoding or - sys.getdefaultencoding()) - err = py.builtin._totext(err, sys.stderr.encoding or - sys.getdefaultencoding()) + if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not + try: + default_encoding = sys.getdefaultencoding() # jython may not have it + except AttributeError: + default_encoding = sys.stdout.encoding or 'UTF-8' + out = unicode(out, process.stdout.encoding or default_encoding) + err = unicode(err, process.stderr.encoding or default_encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) From antocuni at codespeak.net Fri Jun 25 10:48:25 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 25 Jun 2010 10:48:25 +0200 (CEST) Subject: [pypy-svn] r75576 - pypy/trunk/pypy/module Message-ID: <20100625084825.C81E2282B9C@codespeak.net> Author: antocuni Date: Fri Jun 25 10:48:24 2010 New Revision: 75576 Modified: pypy/trunk/pypy/module/conftest.py Log: slightly tweak the collection process so that now it's possible again to run e.g. py.test test_array.py Modified: pypy/trunk/pypy/module/conftest.py ============================================================================== --- pypy/trunk/pypy/module/conftest.py (original) +++ pypy/trunk/pypy/module/conftest.py Fri Jun 25 10:48:24 2010 @@ -2,16 +2,17 @@ from pypy.tool.lib_pypy import LIB_PYPY class MultipleDirCollector(py.test.collect.Collector): - def __init__(self, name, fspaths, parent=None, config=None): + def __init__(self, name, mainfspath, fspaths, parent=None, config=None): super(MultipleDirCollector, self).__init__(name, parent, config) + self.main_collector = py.test.collect.Directory(mainfspath, self) self.collectors = [py.test.collect.Directory(fspath, self) for fspath in fspaths] def collect(self): - return self.collectors + return self.main_collector.collect() + self.collectors def pytest_collect_directory(path, parent): if path.basename == 'test_lib_pypy': # collect all the test in BOTH test_lib_pypy and ../../lib_pypy - return MultipleDirCollector(path.basename, [path, LIB_PYPY], parent) + return MultipleDirCollector(path.basename, path, [LIB_PYPY], parent) From antocuni at codespeak.net Fri Jun 25 10:55:32 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 25 Jun 2010 10:55:32 +0200 (CEST) Subject: [pypy-svn] r75577 - pypy/trunk/pypy/translator/cli Message-ID: <20100625085532.6D26D282BD4@codespeak.net> Author: antocuni Date: Fri Jun 25 10:55:30 2010 New Revision: 75577 Modified: pypy/trunk/pypy/translator/cli/support.py Log: (thanks magcius) missing import Modified: pypy/trunk/pypy/translator/cli/support.py ============================================================================== --- pypy/trunk/pypy/translator/cli/support.py (original) +++ pypy/trunk/pypy/translator/cli/support.py Fri Jun 25 10:55:30 2010 @@ -1,3 +1,4 @@ +import sys import py from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.rte import Support From tobami at codespeak.net Fri Jun 25 11:46:31 2010 From: tobami at codespeak.net (tobami at codespeak.net) Date: Fri, 25 Jun 2010 11:46:31 +0200 (CEST) Subject: [pypy-svn] r75578 - in pypy/benchmarks: . test Message-ID: <20100625094631.2B4D2282B9C@codespeak.net> Author: tobami Date: Fri Jun 25 11:46:29 2010 New Revision: 75578 Modified: pypy/benchmarks/runner.py pypy/benchmarks/saveresults.py pypy/benchmarks/test/test_saveresults.py Log: Update saving scripts to new codespeed version Modified: pypy/benchmarks/runner.py ============================================================================== --- pypy/benchmarks/runner.py (original) +++ pypy/benchmarks/runner.py Fri Jun 25 11:46:29 2010 @@ -34,22 +34,20 @@ f.close() if upload: from saveresults import save - project = 'pypy' + project = 'PyPy' if "--jit threshold" in args: name = "pypy-c" else: name = "pypy-c-jit" - optionsname = "" if "psyco.sh" in pypy_c_path: - name = "cpython" - optionsname = "psyco-profile" - revision = 262 + name = "cpython psyco-profile" + revision = 100 project = 'cpython' if force_host is not None: host = force_host else: host = socket.gethostname() - save(project, revision, res, options, branch, name, optionsname, host) + save(project, revision, res, options, name, host) BENCHMARK_SET = ['richards', 'slowspitfire', 'django', 'spambayes', 'rietveld', 'html5lib', 'ai'] Modified: pypy/benchmarks/saveresults.py ============================================================================== --- pypy/benchmarks/saveresults.py (original) +++ pypy/benchmarks/saveresults.py Fri Jun 25 11:46:29 2010 @@ -8,12 +8,10 @@ SPEEDURL = "http://speed.pypy.org/" -def save(project, revision, results, options, branch, interpreter, - int_options, host, testing=False): +def save(project, revision, results, options, interpreter, host, testing=False): testparams = [] #Parse data data = {} - current_date = datetime.today() error = 0 for b in results: @@ -31,12 +29,10 @@ data = { 'commitid': revision, 'project': project, - 'executable_name': interpreter, - 'executable_coptions': int_options, + 'executable': interpreter, 'benchmark': bench_name, 'environment': host, 'result_value': value, - 'result_date': current_date, } if res_type == "ComparisonResult": data['std_dev'] = results['std_changed'] @@ -52,7 +48,7 @@ params = urllib.urlencode(data) f = None response = "None" - info = str(datetime.today()) + ": Saving result for " + data['executable_name'] + " revision " + info = str(datetime.today()) + ": Saving result for " + data['executable'] + " revision " info += str(data['commitid']) + ", benchmark " + data['benchmark'] print(info) try: Modified: pypy/benchmarks/test/test_saveresults.py ============================================================================== --- pypy/benchmarks/test/test_saveresults.py (original) +++ pypy/benchmarks/test/test_saveresults.py Fri Jun 25 11:46:29 2010 @@ -22,12 +22,10 @@ def test_good_input(self): '''Given correct result data, check that every result being saved has the right parameters''' - for resultparams in saveresults.save("pypy", 71212, self.fixture, "", "experimental", "pypy-c-jit", "gc=hybrid", 'host', True): - assert resultparams['project'] == "pypy" + for resultparams in saveresults.save("PyPy", 71212, self.fixture, "", "pypy-c-jit", 'host', True): + assert resultparams['project'] == "PyPy" assert resultparams['commitid'] == 71212 - assert resultparams['branch'] == "experimental" - assert resultparams['executable_name'] == "pypy-c-jit" - assert resultparams['executable_coptions'] == "gc=hybrid" + assert resultparams['executable'] == "pypy-c-jit" # get dict with correct data for this benchmark fixturedata = [] benchfound = False From arigo at codespeak.net Fri Jun 25 12:23:58 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Jun 2010 12:23:58 +0200 (CEST) Subject: [pypy-svn] r75579 - pypy/trunk/pypy/translator/backendopt/test Message-ID: <20100625102358.4FC0D282B9C@codespeak.net> Author: arigo Date: Fri Jun 25 12:23:56 2010 New Revision: 75579 Modified: pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py Log: Bah. Modified: pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py Fri Jun 25 12:23:56 2010 @@ -169,7 +169,7 @@ t, graph = rtype(entrypoint, [int]) total0 = preparation(t, t.graphs, heuristic=heuristic) total = clever_inlining_and_malloc_removal(t) - assert total0 + total == 16 + assert total == 5 # XXX total0 appears to vary def test_richards(): from pypy.translator.goal.richards import entry_point From arigo at codespeak.net Fri Jun 25 12:29:58 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Jun 2010 12:29:58 +0200 (CEST) Subject: [pypy-svn] r75580 - pypy/trunk/pypy/interpreter/test Message-ID: <20100625102958.14F16282B9C@codespeak.net> Author: arigo Date: Fri Jun 25 12:29:56 2010 New Revision: 75580 Modified: pypy/trunk/pypy/interpreter/test/test_module.py Log: Typo. Modified: pypy/trunk/pypy/interpreter/test/test_module.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_module.py (original) +++ pypy/trunk/pypy/interpreter/test/test_module.py Fri Jun 25 12:29:56 2010 @@ -58,7 +58,7 @@ r = repr(_pypy_interact) assert (r.startswith("')) nofile = type(_pypy_interact)('nofile', 'foo') assert repr(nofile) == "" From arigo at codespeak.net Fri Jun 25 12:33:53 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Jun 2010 12:33:53 +0200 (CEST) Subject: [pypy-svn] r75581 - pypy/trunk/pypy/objspace/std/test Message-ID: <20100625103353.E6719282B9C@codespeak.net> Author: arigo Date: Fri Jun 25 12:33:52 2010 New Revision: 75581 Modified: pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py Log: Attempt to reduce randomness here. Modified: pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py Fri Jun 25 12:33:52 2010 @@ -209,6 +209,7 @@ a = A() names = [name for name in A.__dict__.keys() if not name.startswith('_')] + names.sort() names_repeated = names * 10 result = [] __pypy__.reset_method_cache_counter() From afa at codespeak.net Fri Jun 25 13:31:16 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 13:31:16 +0200 (CEST) Subject: [pypy-svn] r75583 - pypy/trunk/pypy/translator/platform Message-ID: <20100625113116.1E969282B9C@codespeak.net> Author: afa Date: Fri Jun 25 13:31:14 2010 New Revision: 75583 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: Visual Studio 2010 requires the /MANIFEST option to generate manifest files Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Fri Jun 25 13:31:14 2010 @@ -168,7 +168,7 @@ # Tell the linker to generate a manifest file temp_manifest = ofile.dirpath().join( ofile.purebasename + '.manifest') - args += ["/MANIFESTFILE:%s" % (temp_manifest,)] + args += ["/MANIFEST", "/MANIFESTFILE:%s" % (temp_manifest,)] self._execute_c_compiler(self.link, args, exe_name) @@ -277,7 +277,7 @@ '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) /out:$@ $(LIBDIRS) $(LIBS)') else: m.rule('$(TARGET)', '$(OBJECTS)', - ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFEST /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) @@ -290,7 +290,7 @@ 'int main(int argc, char* argv[]) ' '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@') m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'], - ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFESTFILE:$*.manifest', + ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFEST /MANIFESTFILE:$*.manifest', 'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1', ]) From antocuni at codespeak.net Fri Jun 25 15:08:47 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 25 Jun 2010 15:08:47 +0200 (CEST) Subject: [pypy-svn] r75586 - in pypy/trunk/lib-python/modified-2.5.2: . distutils distutils/command Message-ID: <20100625130847.7DEC2282B9C@codespeak.net> Author: antocuni Date: Fri Jun 25 15:08:45 2010 New Revision: 75586 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/trunk/lib-python/modified-2.5.2/site.py Log: fix distutils for the new directory layout. setuptools and easy_install work again now Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/cmd.py Fri Jun 25 15:08:45 2010 @@ -17,9 +17,9 @@ def _easy_install_get_site_dirs(): # return a list of 'site' dirs for easy_install from pkg_resources import normalize_path + from distutils.sysconfig import get_python_lib sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep)) - pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] - sitedirs.append(os.path.join(sys.prefix, 'lib', pypylib, 'site-packages')) + sitedirs.append(get_python_lib(standard_lib=False)) sitedirs = map(normalize_path, sitedirs) return sitedirs Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/command/install.py Fri Jun 25 15:08:45 2010 @@ -67,8 +67,8 @@ 'data' : '$base', }, 'pypy': { - 'purelib': '$base/lib/pypy$pypy_version_short/site-packages', - 'platlib': '$base/lib/pypy$pypy_version_short/site-packages', + 'purelib': '$base/site-packages', + 'platlib': '$base/site-packages', 'headers': '$base/include', 'scripts': '$base/bin', 'data' : '$base', Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Fri Jun 25 15:08:45 2010 @@ -13,7 +13,7 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j - cand = j(sys.pypy_prefix, 'include') + cand = j(sys.prefix, 'include') if os.path.exists(cand): return cand if plat_specific: @@ -47,8 +47,11 @@ "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: prefix = PREFIX - pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] - return os.path.join(prefix, 'lib', pypylib, 'site-packages') + pypylib = os.path.join(prefix, 'lib', 'pypy%d.%d' % sys.pypy_version_info[:2]) + if os.path.exists(pypylib): + return os.path.join(pypylib, 'site-packages') + else: + return os.path.join(prefix, 'site-packages') _config_vars = None Modified: pypy/trunk/lib-python/modified-2.5.2/site.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/site.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/site.py Fri Jun 25 15:08:45 2010 @@ -176,8 +176,8 @@ def addsitepackages(known_paths): """Add site-packages to sys.path, in a PyPy-specific way.""" if hasattr(sys, 'pypy_version_info'): - pypylib = 'pypy%d.%d' % sys.pypy_version_info[:2] - sitedir = os.path.join(sys.prefix, 'lib', pypylib, 'site-packages') + from distutils.sysconfig import get_python_lib + sitedir = get_python_lib(standard_lib=False) if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) return None From antocuni at codespeak.net Fri Jun 25 15:19:34 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 25 Jun 2010 15:19:34 +0200 (CEST) Subject: [pypy-svn] r75587 - pypy/branch/sys-prefix Message-ID: <20100625131934.060BA282B9C@codespeak.net> Author: antocuni Date: Fri Jun 25 15:19:33 2010 New Revision: 75587 Removed: pypy/branch/sys-prefix/ Log: remove merged branch From afa at codespeak.net Fri Jun 25 15:36:48 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 15:36:48 +0200 (CEST) Subject: [pypy-svn] r75588 - pypy/trunk/pypy/translator/c/gcc Message-ID: <20100625133648.DC54A282B9C@codespeak.net> Author: afa Date: Fri Jun 25 15:36:47 2010 New Revision: 75588 Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Log: clang generates "jmpl" instructions Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Fri Jun 25 15:36:47 2010 @@ -641,6 +641,7 @@ self.register_jump_to(label) return [] + visit_jmpl = visit_jmp visit_je = conditional_jump visit_jne = conditional_jump visit_jg = conditional_jump From afa at codespeak.net Fri Jun 25 15:38:24 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 15:38:24 +0200 (CEST) Subject: [pypy-svn] r75589 - pypy/branch/interplevel-codecs Message-ID: <20100625133824.C72A4282B9C@codespeak.net> Author: afa Date: Fri Jun 25 15:38:23 2010 New Revision: 75589 Added: pypy/branch/interplevel-codecs/ (props changed) - copied from r75588, pypy/trunk/ Log: A branch to rewrite app_codecs.py and reduce code bloat From hpk at codespeak.net Fri Jun 25 15:46:22 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 25 Jun 2010 15:46:22 +0200 (CEST) Subject: [pypy-svn] r75590 - in pypy/trunk/pypy: rpython/microbench tool/test translator translator/cli translator/cli/test translator/jvm translator/jvm/test Message-ID: <20100625134622.EB545282B9C@codespeak.net> Author: hpk Date: Fri Jun 25 15:46:20 2010 New Revision: 75590 Modified: pypy/trunk/pypy/rpython/microbench/microbench.py pypy/trunk/pypy/tool/test/test_killsubprocess.py pypy/trunk/pypy/translator/cli/gencli.py pypy/trunk/pypy/translator/cli/query.py pypy/trunk/pypy/translator/cli/rte.py pypy/trunk/pypy/translator/cli/test/runtest.py pypy/trunk/pypy/translator/driver.py pypy/trunk/pypy/translator/jvm/genjvm.py pypy/trunk/pypy/translator/jvm/test/runtest.py Log: remove long deprecated usage of py.compat namespace Modified: pypy/trunk/pypy/rpython/microbench/microbench.py ============================================================================== --- pypy/trunk/pypy/rpython/microbench/microbench.py (original) +++ pypy/trunk/pypy/rpython/microbench/microbench.py Fri Jun 25 15:46:20 2010 @@ -3,7 +3,7 @@ import sys import autopath from time import clock -from py.compat import subprocess +import subprocess from pypy.translator.interactive import Translation LOOPS = 10000000 Modified: pypy/trunk/pypy/tool/test/test_killsubprocess.py ============================================================================== --- pypy/trunk/pypy/tool/test/test_killsubprocess.py (original) +++ pypy/trunk/pypy/tool/test/test_killsubprocess.py Fri Jun 25 15:46:20 2010 @@ -1,5 +1,5 @@ import sys, time -from py.compat import subprocess +import subprocess from pypy.tool.killsubprocess import killsubprocess def waitdead(process): Modified: pypy/trunk/pypy/translator/cli/gencli.py ============================================================================== --- pypy/trunk/pypy/translator/cli/gencli.py (original) +++ pypy/trunk/pypy/translator/cli/gencli.py Fri Jun 25 15:46:20 2010 @@ -2,7 +2,7 @@ import shutil import py -from py.compat import subprocess +import subprocess from pypy.config.config import Config from pypy.translator.oosupport.genoo import GenOO from pypy.translator.cli import conftest Modified: pypy/trunk/pypy/translator/cli/query.py ============================================================================== --- pypy/trunk/pypy/translator/cli/query.py (original) +++ pypy/trunk/pypy/translator/cli/query.py Fri Jun 25 15:46:20 2010 @@ -2,7 +2,7 @@ import cPickle as pickle import os.path import py -from py.compat import subprocess +import subprocess from pypy.tool.udir import udir from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.rte import Query Modified: pypy/trunk/pypy/translator/cli/rte.py ============================================================================== --- pypy/trunk/pypy/translator/cli/rte.py (original) +++ pypy/trunk/pypy/translator/cli/rte.py Fri Jun 25 15:46:20 2010 @@ -7,7 +7,7 @@ import shutil import py -from py.compat import subprocess +import subprocess from pypy.translator.cli.sdk import SDK from pypy.tool.ansi_print import ansi_log log = py.log.Producer("cli") Modified: pypy/trunk/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/trunk/pypy/translator/cli/test/runtest.py (original) +++ pypy/trunk/pypy/translator/cli/test/runtest.py Fri Jun 25 15:46:20 2010 @@ -2,7 +2,7 @@ import platform import py -from py.compat import subprocess +import subprocess from pypy.tool.udir import udir from pypy.translator.translator import TranslationContext from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin Modified: pypy/trunk/pypy/translator/driver.py ============================================================================== --- pypy/trunk/pypy/translator/driver.py (original) +++ pypy/trunk/pypy/translator/driver.py Fri Jun 25 15:46:20 2010 @@ -729,7 +729,7 @@ 'Compiling JVM source') def copy_jvm_jar(self): - from py.compat import subprocess + import subprocess basename = self.exe_name % self.get_info() root = udir.join('pypy') manifest = self.create_manifest(root) @@ -764,7 +764,7 @@ return filename def create_classlist(self, root, additional_jars=[]): - from py.compat import subprocess + import subprocess # first, uncompress additional jars for jarfile in additional_jars: oldpwd = root.chdir() Modified: pypy/trunk/pypy/translator/jvm/genjvm.py ============================================================================== --- pypy/trunk/pypy/translator/jvm/genjvm.py (original) +++ pypy/trunk/pypy/translator/jvm/genjvm.py Fri Jun 25 15:46:20 2010 @@ -6,7 +6,7 @@ import os import py -from py.compat import subprocess +import subprocess from pypy.tool.udir import udir from pypy.translator.translator import TranslationContext from pypy.translator.oosupport.genoo import GenOO Modified: pypy/trunk/pypy/translator/jvm/test/runtest.py ============================================================================== --- pypy/trunk/pypy/translator/jvm/test/runtest.py (original) +++ pypy/trunk/pypy/translator/jvm/test/runtest.py Fri Jun 25 15:46:20 2010 @@ -2,7 +2,7 @@ import platform import py -from py.compat import subprocess +import subprocess from pypy.tool.udir import udir from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin from pypy.rpython.lltypesystem.lltype import typeOf From afa at codespeak.net Fri Jun 25 15:49:12 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 15:49:12 +0200 (CEST) Subject: [pypy-svn] r75591 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100625134912.9AE98282B9C@codespeak.net> Author: afa Date: Fri Jun 25 15:49:11 2010 New Revision: 75591 Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: Move code, order functions by codec Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Fri Jun 25 15:49:11 2010 @@ -55,8 +55,8 @@ assert isinstance(u, unicode) raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg) -# ____________________________________________________________ -# unicode decoding +# ____________________________________________________________ +# utf-8 utf8_code_length = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -199,6 +199,51 @@ return u"".join(result), pos +def _encodeUCS4(result, ch): + # Encode UCS4 Unicode ordinals + result.append((chr((0xf0 | (ch >> 18))))) + result.append((chr((0x80 | ((ch >> 12) & 0x3f))))) + result.append((chr((0x80 | ((ch >> 6) & 0x3f))))) + result.append((chr((0x80 | (ch & 0x3f))))) + +def unicode_encode_utf_8(s, size, errors, errorhandler=None): + assert(size >= 0) + result = [] + i = 0 + while i < size: + ch = ord(s[i]) + i += 1 + if (ch < 0x80): + # Encode ASCII + result.append(chr(ch)) + elif (ch < 0x0800) : + # Encode Latin-1 + result.append(chr((0xc0 | (ch >> 6)))) + result.append(chr((0x80 | (ch & 0x3f)))) + else: + # Encode UCS2 Unicode ordinals + if (ch < 0x10000): + # Special case: check for high surrogate + if (0xD800 <= ch and ch <= 0xDBFF and i != size) : + ch2 = ord(s[i]) + # Check for low surrogate and combine the two to + # form a UCS4 value + if (0xDC00 <= ch2 and ch2 <= 0xDFFF) : + ch3 = ((ch - 0xD800) << 10 | (ch2 - 0xDC00)) + 0x10000 + i += 1 + _encodeUCS4(result, ch3) + continue + # Fall through: handles isolated high surrogates + result.append((chr((0xe0 | (ch >> 12))))) + result.append((chr((0x80 | ((ch >> 6) & 0x3f))))) + result.append((chr((0x80 | (ch & 0x3f))))) + continue + else: + _encodeUCS4(result, ch) + return "".join(result) + +# ____________________________________________________________ +# utf-16 def str_decode_utf_16(s, size, errors, final=True, errorhandler=None): @@ -320,6 +365,60 @@ result.append(r) return u"".join(result), pos, bo +def _STORECHAR(result, CH, byteorder): + hi = chr(((CH) >> 8) & 0xff) + lo = chr((CH) & 0xff) + if byteorder == 'little': + result.append(lo) + result.append(hi) + else: + result.append(hi) + result.append(lo) + +def unicode_encode_utf_16_helper(s, size, errors, + errorhandler=None, + byteorder='little'): + result = [] + if (byteorder == 'native'): + _STORECHAR(result, 0xFEFF, BYTEORDER) + byteorder = BYTEORDER + + if size == 0: + return "" + + i = 0 + while i < size: + ch = ord(s[i]) + i += 1 + ch2 = 0 + if (ch >= 0x10000) : + ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF) + ch = 0xD800 | ((ch-0x10000) >> 10) + + _STORECHAR(result, ch, byteorder) + if ch2: + _STORECHAR(result, ch2, byteorder) + + return "".join(result) + +def unicode_encode_utf_16(s, size, errors, + errorhandler=None): + return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "native") + + +def unicode_encode_utf_16_be(s, size, errors, + errorhandler=None): + return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "big") + + +def unicode_encode_utf_16_le(s, size, errors, + errorhandler=None): + return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "little") + + +# ____________________________________________________________ +# ascii and latin-1 + def str_decode_latin_1(s, size, errors, final=False, errorhandler=None): # latin1 is equivalent to the first 256 ordinals in Unicode. @@ -350,54 +449,6 @@ return u"".join(result), pos -# ____________________________________________________________ -# unicode encoding - - -def unicode_encode_utf_8(s, size, errors, errorhandler=None): - assert(size >= 0) - result = [] - i = 0 - while i < size: - ch = ord(s[i]) - i += 1 - if (ch < 0x80): - # Encode ASCII - result.append(chr(ch)) - elif (ch < 0x0800) : - # Encode Latin-1 - result.append(chr((0xc0 | (ch >> 6)))) - result.append(chr((0x80 | (ch & 0x3f)))) - else: - # Encode UCS2 Unicode ordinals - if (ch < 0x10000): - # Special case: check for high surrogate - if (0xD800 <= ch and ch <= 0xDBFF and i != size) : - ch2 = ord(s[i]) - # Check for low surrogate and combine the two to - # form a UCS4 value - if (0xDC00 <= ch2 and ch2 <= 0xDFFF) : - ch3 = ((ch - 0xD800) << 10 | (ch2 - 0xDC00)) + 0x10000 - i += 1 - _encodeUCS4(result, ch3) - continue - # Fall through: handles isolated high surrogates - result.append((chr((0xe0 | (ch >> 12))))) - result.append((chr((0x80 | ((ch >> 6) & 0x3f))))) - result.append((chr((0x80 | (ch & 0x3f))))) - continue - else: - _encodeUCS4(result, ch) - return "".join(result) - -def _encodeUCS4(result, ch): - # Encode UCS4 Unicode ordinals - result.append((chr((0xf0 | (ch >> 18))))) - result.append((chr((0x80 | ((ch >> 12) & 0x3f))))) - result.append((chr((0x80 | ((ch >> 6) & 0x3f))))) - result.append((chr((0x80 | (ch & 0x3f))))) - - def unicode_encode_ucs1_helper(p, size, errors, errorhandler=None, limit=256): if errorhandler is None: @@ -440,57 +491,6 @@ return res -def _STORECHAR(result, CH, byteorder): - hi = chr(((CH) >> 8) & 0xff) - lo = chr((CH) & 0xff) - if byteorder == 'little': - result.append(lo) - result.append(hi) - else: - result.append(hi) - result.append(lo) - -def unicode_encode_utf_16_helper(s, size, errors, - errorhandler=None, - byteorder='little'): - result = [] - if (byteorder == 'native'): - _STORECHAR(result, 0xFEFF, BYTEORDER) - byteorder = BYTEORDER - - if size == 0: - return "" - - i = 0 - while i < size: - ch = ord(s[i]) - i += 1 - ch2 = 0 - if (ch >= 0x10000) : - ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF) - ch = 0xD800 | ((ch-0x10000) >> 10) - - _STORECHAR(result, ch, byteorder) - if ch2: - _STORECHAR(result, ch2, byteorder) - - return "".join(result) - -def unicode_encode_utf_16(s, size, errors, - errorhandler=None): - return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "native") - - -def unicode_encode_utf_16_be(s, size, errors, - errorhandler=None): - return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "big") - - -def unicode_encode_utf_16_le(s, size, errors, - errorhandler=None): - return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "little") - - # ____________________________________________________________ # MBCS codecs for Windows From jcreigh at codespeak.net Fri Jun 25 16:04:40 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Fri, 25 Jun 2010 16:04:40 +0200 (CEST) Subject: [pypy-svn] r75592 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100625140440.AF8E8282B9C@codespeak.net> Author: jcreigh Date: Fri Jun 25 16:04:39 2010 New Revision: 75592 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: clean up regloc some and stop saying CALL_j when we mean CALL_i Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Fri Jun 25 16:04:39 2010 @@ -21,7 +21,7 @@ X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG, RegLoc, StackLoc, - ImmedLoc, AddressLoc, imm, rel32) + ImmedLoc, AddressLoc, imm) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import rx86, regloc, codebuf @@ -217,7 +217,7 @@ mc.MOV_rr(edi.value, edx.value) addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr() - mc.JMP_l(addr) # tail call to the real malloc + mc.JMP(imm(addr)) # tail call to the real malloc # ---------- second helper for the slow path of malloc ---------- self.malloc_fixedsize_slowpath2 = mc.tell() if self.cpu.supports_floats: # restore the XMM registers @@ -784,7 +784,7 @@ self.mark_gc_roots() def call(self, addr, args, res): - self._emit_call(rel32(addr), args) + self._emit_call(imm(addr), args) assert res is eax genop_int_neg = _unaryop("NEG") @@ -893,7 +893,7 @@ return self.implement_guard(guard_token, 'Z') def genop_int_is_zero(self, op, arglocs, resloc): - self.mc.CMP(arglocs[0], imm8(0)) + self.mc.CMP(arglocs[0], imm(0)) rl = resloc.lowest8bits() self.mc.SET_ir(rx86.Conditions['E'], rl.value) self.mc.MOVZX8(resloc, rl) @@ -976,11 +976,11 @@ assert isinstance(ofs, ImmedLoc) assert isinstance(scale, ImmedLoc) if op.result.type == FLOAT: - self.mc.MOVSD(resloc, addr64_add(base_loc, ofs_loc, ofs.value, + self.mc.MOVSD(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) else: if scale.value == 0: - self.mc.MOVZX8(resloc, addr8_add(base_loc, ofs_loc, ofs.value, + self.mc.MOVZX8(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) elif (1 << scale.value) == WORD: self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, ofs.value, @@ -1172,7 +1172,7 @@ def genop_guard_guard_nonnull_class(self, ign_1, guard_op, guard_token, locs, ign_2): mc = self._start_block() - mc.CMP(locs[0], imm8(1)) + mc.CMP(locs[0], imm(1)) # Patched below mc.J_il8(rx86.Conditions['B'], 0) jb_location = mc.get_relative_pos() @@ -1515,7 +1515,7 @@ size = sizeloc.value if isinstance(op.args[0], Const): - x = rel32(op.args[0].getint()) + x = imm(op.args[0].getint()) else: x = arglocs[1] if x is eax: @@ -1551,7 +1551,7 @@ assert len(arglocs) - 2 == len(descr._x86_arglocs[0]) # # Write a call to the direct_bootstrap_code of the target assembler - self._emit_call(rel32(descr._x86_direct_bootstrap_code), arglocs, 2, + self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) mc = self._start_block() if op.result is None: @@ -1575,7 +1575,7 @@ je_location = mc.get_relative_pos() # # Path A: use assembler_helper_adr - self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, + self._emit_call(imm(self.assembler_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: mc.FSTP_b(result_loc.value) @@ -1655,7 +1655,7 @@ # misaligned stack in the call, but it's ok because the write barrier # is not going to call anything more. Also, this assumes that the # write barrier does not touch the xmm registers. - mc.CALL(heap(descr.get_write_barrier_fn(self.cpu))) + mc.CALL(imm(descr.get_write_barrier_fn(self.cpu))) for i in range(len(arglocs)): loc = arglocs[i] assert isinstance(loc, RegLoc) @@ -1759,11 +1759,8 @@ return size # XXX: ri386 migration shims: - def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): return AddressLoc(reg_or_imm1, reg_or_imm2, scale, offset) -addr64_add = addr_add -addr8_add = addr_add def addr_add_const(reg_or_imm1, offset): return AddressLoc(reg_or_imm1, ImmedLoc(0), 0, offset) @@ -1773,5 +1770,3 @@ def heap(addr): return AddressLoc(ImmedLoc(addr), ImmedLoc(0), 0, 0) - -imm8 = imm Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Fri Jun 25 16:04:39 2010 @@ -3,6 +3,7 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.jit.backend.x86.arch import WORD from pypy.tool.sourcetools import func_with_new_name +from pypy.rlib.objectmodel import specialize # # This module adds support for "locations", which can be either in a Const, @@ -155,6 +156,13 @@ unrolling_location_codes = unrolling_iterable(list("rbsmajix")) + at specialize.arg(1) +def _rx86_getattr(obj, methname): + if hasattr(rx86.AbstractX86CodeBuilder, methname): + return getattr(obj, methname) + else: + raise AssertionError(methname + " undefined") + class LocationCodeBuilder(object): _mixin_ = True @@ -170,47 +178,34 @@ if code1 == possible_code1: for possible_code2 in unrolling_location_codes: if code2 == possible_code2: - # FIXME: Not RPython anymore! - # Fake out certain operations for x86_64 val1 = getattr(loc1, "value_" + possible_code1)() val2 = getattr(loc2, "value_" + possible_code2)() - # XXX: Could use RIP+disp32 in some cases + # Fake out certain operations for x86_64 if self.WORD == 8 and possible_code2 == 'i' and not rx86.fits_in_32bits(val2): if possible_code1 == 'j': - # This is the worst case: MOV_ji, and both operands are 64-bit + # This is the worst case: INSN_ji, and both operands are 64-bit # Hopefully this doesn't happen too often self.PUSH_r(eax.value) self.MOV_ri(eax.value, val1) self.MOV_ri(X86_64_SCRATCH_REG.value, val2) - self.MOV_mr((eax.value, 0), X86_64_SCRATCH_REG.value) + methname = name + "_mr" + _rx86_getattr(self, methname)((eax.value, 0), X86_64_SCRATCH_REG.value) self.POP_r(eax.value) else: self.MOV_ri(X86_64_SCRATCH_REG.value, val2) methname = name + "_" + possible_code1 + "r" - if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)(val1, X86_64_SCRATCH_REG.value) - else: - assert False, "a" + _rx86_getattr(self, methname)(val1, X86_64_SCRATCH_REG.value) elif self.WORD == 8 and possible_code1 == 'j': reg_offset = self._addr_as_reg_offset(val1) methname = name + "_" + "m" + possible_code2 - if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)(reg_offset, val2) - else: - assert False, "b" + _rx86_getattr(self, methname)(reg_offset, val2) elif self.WORD == 8 and possible_code2 == 'j': reg_offset = self._addr_as_reg_offset(val2) methname = name + "_" + possible_code1 + "m" - if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)(val1, reg_offset) - else: - assert False, "c" + _rx86_getattr(self, methname)(val1, reg_offset) else: methname = name + "_" + possible_code1 + possible_code2 - if hasattr(rx86.AbstractX86CodeBuilder, methname): - getattr(self, methname)(val1, val2) - else: - assert False, "d" + _rx86_getattr(self, methname)(val1, val2) return func_with_new_name(INSN, "INSN_" + name) @@ -219,13 +214,13 @@ code = loc.location_code() for possible_code in unrolling_location_codes: if code == possible_code: - methname = name + "_" + possible_code - if hasattr(rx86.AbstractX86CodeBuilder, methname): - val = getattr(loc, "value_" + possible_code)() - getattr(self, methname)(val) - return + val = getattr(loc, "value_" + possible_code)() + if self.WORD == 8 and possible_code == 'i' and not rx86.fits_in_32bits(val): + self.MOV_ri(X86_64_SCRATCH_REG.value, val) + _rx86_getattr(self, name + "_r")(X86_64_SCRATCH_REG.value) else: - raise AssertionError("Instruction not defined: " + methname) + methname = name + "_" + possible_code + _rx86_getattr(self, methname)(val) return func_with_new_name(INSN, "INSN_" + name) @@ -312,6 +307,7 @@ XORPD = _binaryop('XORPD') CALL = _unaryop('CALL') + JMP = _unaryop('JMP') def imm(x): # XXX: ri386 migration shim @@ -320,10 +316,6 @@ else: return ImmedLoc(x) -def rel32(x): - # XXX: ri386 migration shim - return AddressLoc(ImmedLoc(x), ImmedLoc(0)) - all_extra_instructions = [name for name in LocationCodeBuilder.__dict__ if name[0].isupper()] all_extra_instructions.sort() Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Fri Jun 25 16:04:39 2010 @@ -489,6 +489,8 @@ XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') JMP_l = insn('\xE9', relative(1)) + # FIXME + JMP_i = JMP_l JMP_r = insn(rex_nw, '\xFF', orbyte(4<<3), register(1), '\xC0') # FIXME: J_il8 and JMP_l8 assume the caller will do the appropriate # calculation to find the displacement, but J_il does it for the caller. @@ -518,7 +520,7 @@ CVTTSD2SI_rb = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), stack_bp(2)) # XXX: hack - def CALL_j(self): + def CALL_i(self): assert False # ------------------------------------------------------------ @@ -555,7 +557,7 @@ # XXX: Bit of kludge, but works in 32-bit because the relative 32-bit # displacement is always enough to encode any address - CALL_j = AbstractX86CodeBuilder.CALL_l + CALL_i = AbstractX86CodeBuilder.CALL_l class X86_64_CodeBuilder(AbstractX86CodeBuilder): @@ -595,7 +597,7 @@ AbstractX86CodeBuilder.CALL_r(self, R.eax) # XXX - CALL_j = CALL_l + CALL_i = CALL_l def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): From afa at codespeak.net Fri Jun 25 16:28:51 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 25 Jun 2010 16:28:51 +0200 (CEST) Subject: [pypy-svn] r75594 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100625142851.87276282B9C@codespeak.net> Author: afa Date: Fri Jun 25 16:28:50 2010 New Revision: 75594 Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: While I'm at it, use StringBuilder instead of "".join Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Fri Jun 25 16:28:50 2010 @@ -2,6 +2,7 @@ from pypy.rlib.bitmanipulation import splitter from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder if rffi.sizeof(lltype.UniChar) == 4: MAXUNICODE = 0x10ffff @@ -42,8 +43,6 @@ UNICHR = unichr ORD = ord -# XXX review the functions below and think about using stringbuilders for them - def raise_unicode_exception_decode(errors, encoding, msg, s, startingpos, endingpos): @@ -83,7 +82,8 @@ errorhandler = raise_unicode_exception_decode if (size == 0): return u'', 0 - result = [] + + result = UnicodeBuilder(size) pos = 0 while pos < size: ch = s[pos] @@ -197,7 +197,7 @@ s, pos, pos + n) result.append(r) - return u"".join(result), pos + return result.build(), pos def _encodeUCS4(result, ch): # Encode UCS4 Unicode ordinals @@ -208,7 +208,7 @@ def unicode_encode_utf_8(s, size, errors, errorhandler=None): assert(size >= 0) - result = [] + result = StringBuilder(size) i = 0 while i < size: ch = ord(s[i]) @@ -240,7 +240,7 @@ continue else: _encodeUCS4(result, ch) - return "".join(result) + return result.build() # ____________________________________________________________ # utf-16 @@ -283,7 +283,6 @@ # mark is skipped, in all other modes, it is copied to the output # stream as-is (giving a ZWNBSP character). pos = 0 - result = [] if byteorder == 'native': if (size >= 2): bom = (ord(s[ihi]) << 8) | ord(s[ilo]) @@ -317,6 +316,8 @@ ihi = 0 ilo = 1 + result = UnicodeBuilder(size // 2) + #XXX I think the errors are not correctly handled here while (pos < len(s)): # remaining bytes at the end? (size should be even) @@ -363,7 +364,7 @@ "illegal encoding", s, pos - 2, pos) result.append(r) - return u"".join(result), pos, bo + return result.build(), pos, bo def _STORECHAR(result, CH, byteorder): hi = chr(((CH) >> 8) & 0xff) @@ -378,13 +379,13 @@ def unicode_encode_utf_16_helper(s, size, errors, errorhandler=None, byteorder='little'): - result = [] + if size == 0: + return "" + + result = StringBuilder(size * 2 + 2) if (byteorder == 'native'): _STORECHAR(result, 0xFEFF, BYTEORDER) byteorder = BYTEORDER - - if size == 0: - return "" i = 0 while i < size: @@ -399,7 +400,7 @@ if ch2: _STORECHAR(result, ch2, byteorder) - return "".join(result) + return result.build() def unicode_encode_utf_16(s, size, errors, errorhandler=None): @@ -423,11 +424,11 @@ errorhandler=None): # latin1 is equivalent to the first 256 ordinals in Unicode. pos = 0 - result = [] + result = UnicodeBuilder(size) while (pos < size): result.append(unichr(ord(s[pos]))) pos += 1 - return u"".join(result), pos + return result.build(), pos def str_decode_ascii(s, size, errors, final=False, @@ -435,7 +436,7 @@ if errorhandler is None: errorhandler = raise_unicode_exception_decode # ASCII is equivalent to the first 128 ordinals in Unicode. - result = [] + result = UnicodeBuilder(size) pos = 0 while pos < len(s): c = s[pos] @@ -446,7 +447,7 @@ r, pos = errorhandler(errors, "ascii", "ordinal not in range(128)", s, pos, pos + 1) result.append(r) - return u"".join(result), pos + return result.build(), pos def unicode_encode_ucs1_helper(p, size, errors, @@ -462,7 +463,7 @@ if (size == 0): return '' - result = [] + result = StringBuilder(size) pos = 0 while pos < len(p): ch = p[pos] @@ -478,9 +479,9 @@ collend += 1 r, pos = errorhandler(errors, encoding, reason, p, collstart, collend) - result += r # extend 'result' as a list of characters + result.append(r) - return "".join(result) + return result.build() def unicode_encode_latin_1(p, size, errors, errorhandler=None): res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 256) From benjamin at codespeak.net Fri Jun 25 16:34:13 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 16:34:13 +0200 (CEST) Subject: [pypy-svn] r75595 - pypy/branch/fast-forward/pypy/interpreter/pyparser/data Message-ID: <20100625143413.6A976282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 16:34:12 2010 New Revision: 75595 Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Log: sync with exact 2.7 grammar Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7 Fri Jun 25 16:34:12 2010 @@ -120,8 +120,12 @@ classdef: 'class' NAME ['(' [testlist] ')'] ':' suite -arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) -argument: test [comp_for] | test '=' test # Really [keyword '='] test +arglist: (argument ',')* (argument [','] + |'*' test (',' argument)* [',' '**' test] + |'**' test) +# The reason that keywords are test nodes instead of NAME is that using NAME +# results in an ambiguity. ast.c makes sure it's a NAME. +argument: test [comp_for] | test '=' test list_iter: list_for | list_if list_for: 'for' exprlist 'in' testlist_safe [list_iter] From benjamin at codespeak.net Fri Jun 25 16:44:29 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 16:44:29 +0200 (CEST) Subject: [pypy-svn] r75596 - in pypy/branch/fast-forward/pypy/interpreter: . astcompiler test Message-ID: <20100625144429.4402F282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 16:44:27 2010 New Revision: 75596 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/pyopcode.py pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Log: implicit set literal opcodes Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Fri Jun 25 16:44:27 2010 @@ -939,6 +939,11 @@ d.keys[i].walkabout(self) self.emit_op(ops.STORE_SUBSCR) + def visit_Set(self, s): + self.update_position(s.lineno) + self.visit_sequence(s.elts) + self.emit_op_arg(ops.BUILD_SET, len(s.elts)) + def visit_Name(self, name): self.update_position(name.lineno) self.name_op(name.id, name.ctx) Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Fri Jun 25 16:44:27 2010 @@ -1062,6 +1062,11 @@ def BUILD_SET(self, itemcount, next_instr): w_set = self.space.call_function(self.space.w_set) + if itemcount: + w_add = self.space.getattr(w_set, self.space.wrap("add")) + for i in range(itemcount): + w_item = self.popvalue() + self.space.call_function(w_add, w_item) self.pushvalue(w_set) def STORE_MAP(self, zero, next_instr): Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py Fri Jun 25 16:44:27 2010 @@ -384,6 +384,14 @@ s = eval("{x for x in range(10) if x % 2}") assert s == set(x for x in range(10) if x % 2) + def test_set_literal(self): + s = eval("{1}") + assert isinstance(s, set) + assert s == set((1,)) + s = eval("{0, 1, 2, 3}") + assert isinstance(s, set) + assert s == set(range(4)) + class AppTestWith: def test_with_simple(self): From jcreigh at codespeak.net Fri Jun 25 16:46:22 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Fri, 25 Jun 2010 16:46:22 +0200 (CEST) Subject: [pypy-svn] r75597 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100625144622.CD513282B9C@codespeak.net> Author: jcreigh Date: Fri Jun 25 16:46:21 2010 New Revision: 75597 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: rx86: tiny cleanup Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Fri Jun 25 16:46:21 2010 @@ -483,14 +483,15 @@ CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) CALL_b = insn('\xFF', orbyte(2<<3), stack_bp(1)) + def CALL_i(self, addr): + self.CALL_l(addr) + # XXX: Only here for testing purposes..."as" happens the encode the # registers in the opposite order that we would otherwise do in a # register-register exchange XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') JMP_l = insn('\xE9', relative(1)) - # FIXME - JMP_i = JMP_l JMP_r = insn(rex_nw, '\xFF', orbyte(4<<3), register(1), '\xC0') # FIXME: J_il8 and JMP_l8 assume the caller will do the appropriate # calculation to find the displacement, but J_il does it for the caller. @@ -519,10 +520,6 @@ CVTTSD2SI_rx = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), register(2), '\xC0') CVTTSD2SI_rb = xmminsn('\xF2', rex_w, '\x0F\x2C', register(1, 8), stack_bp(2)) - # XXX: hack - def CALL_i(self): - assert False - # ------------------------------------------------------------ Conditions = { @@ -577,12 +574,12 @@ # MOV_ri from the parent class is not wrong, but here is a better encoding # for the common case where the immediate fits in 32 bits - _MOV_ri32 = insn(rex_w, '\xC7', register(1), '\xC0', immediate(2, 'i')) + MOV_ri32 = insn(rex_w, '\xC7', register(1), '\xC0', immediate(2, 'i')) MOV_ri64 = AbstractX86CodeBuilder.MOV_ri def MOV_ri(self, reg, immed): if fits_in_32bits(immed): - self._MOV_ri32(reg, immed) + self.MOV_ri32(reg, immed) else: AbstractX86CodeBuilder.MOV_ri(self, reg, immed) @@ -593,11 +590,9 @@ if fits_in_32bits(offset): AbstractX86CodeBuilder.CALL_l(self, target) else: - AbstractX86CodeBuilder.MOV_ri(self, R.eax, target) - AbstractX86CodeBuilder.CALL_r(self, R.eax) + self.MOV_ri(R.eax, target) + self.CALL_r(R.eax) - # XXX - CALL_i = CALL_l def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): From benjamin at codespeak.net Fri Jun 25 16:50:19 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 16:50:19 +0200 (CEST) Subject: [pypy-svn] r75598 - in pypy/branch/fast-forward/pypy/interpreter: . astcompiler Message-ID: <20100625145019.6F949282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 16:50:17 2010 New Revision: 75598 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Log: use the more efficient STORE_MAP for dict literals Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/assemble.py Fri Jun 25 16:50:17 2010 @@ -442,6 +442,7 @@ ops.LIST_APPEND : -1, ops.SET_ADD : -1, ops.MAP_ADD : -2, + ops.STORE_MAP : -2, ops.BINARY_POWER : -1, ops.BINARY_MULTIPLY : -1, Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/codegen.py Fri Jun 25 16:50:17 2010 @@ -933,11 +933,9 @@ self.emit_op_arg(ops.BUILD_MAP, 0) if d.values: for i in range(len(d.values)): - self.emit_op(ops.DUP_TOP) d.values[i].walkabout(self) - self.emit_op(ops.ROT_TWO) d.keys[i].walkabout(self) - self.emit_op(ops.STORE_SUBSCR) + self.emit_op(ops.STORE_MAP) def visit_Set(self, s): self.update_position(s.lineno) Modified: pypy/branch/fast-forward/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/pyopcode.py Fri Jun 25 16:50:17 2010 @@ -1069,8 +1069,11 @@ self.space.call_function(w_add, w_item) self.pushvalue(w_set) - def STORE_MAP(self, zero, next_instr): - raise BytecodeCorruption + def STORE_MAP(self, oparg, next_instr): + w_key = self.popvalue() + w_value = self.popvalue() + w_dict = self.peekvalue() + self.space.setitem(w_dict, w_key, w_value) class __extend__(pyframe.CPythonFrame): From benjamin at codespeak.net Fri Jun 25 16:54:53 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 16:54:53 +0200 (CEST) Subject: [pypy-svn] r75599 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100625145453.8E645282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 16:54:51 2010 New Revision: 75599 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Log: make non-keyword arguments after vararg invalid Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Fri Jun 25 16:54:51 2010 @@ -982,6 +982,9 @@ if keywords: self.error("non-keyword arg after keyword arg", expr_node) + if variable_arg: + self.error("only named arguments may follow " + "*expression", expr_node) args.append(self.handle_expr(expr_node)) elif argument.children[1].type == syms.comp_for: args.append(self.handle_genexp(argument)) Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Fri Jun 25 16:54:51 2010 @@ -992,6 +992,8 @@ assert exc.msg == "keyword can't be an expression" exc = py.test.raises(SyntaxError, self.get_ast, "f(a=c, a=d)").value assert exc.msg == "keyword argument repeated" + exc = py.test.raises(SyntaxError, self.get_ast, "f(x, *a, b)").value + assert exc.msg == "only named arguments may follow *expression" def test_attribute(self): attr = self.get_first_expr("x.y") From jcreigh at codespeak.net Fri Jun 25 17:09:52 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Fri, 25 Jun 2010 17:09:52 +0200 (CEST) Subject: [pypy-svn] r75600 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100625150952.7B510282B9C@codespeak.net> Author: jcreigh Date: Fri Jun 25 17:09:50 2010 New Revision: 75600 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Log: kill rx86 CALL_i (handled in regloc) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Fri Jun 25 17:09:50 2010 @@ -483,9 +483,6 @@ CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) CALL_b = insn('\xFF', orbyte(2<<3), stack_bp(1)) - def CALL_i(self, addr): - self.CALL_l(addr) - # XXX: Only here for testing purposes..."as" happens the encode the # registers in the opposite order that we would otherwise do in a # register-register exchange @@ -552,11 +549,6 @@ CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2)) - # XXX: Bit of kludge, but works in 32-bit because the relative 32-bit - # displacement is always enough to encode any address - CALL_i = AbstractX86CodeBuilder.CALL_l - - class X86_64_CodeBuilder(AbstractX86CodeBuilder): WORD = 8 From benjamin at codespeak.net Fri Jun 25 17:11:06 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 17:11:06 +0200 (CEST) Subject: [pypy-svn] r75601 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100625151106.B0A0D282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 17:11:05 2010 New Revision: 75601 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Log: obscure syntax case Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Fri Jun 25 17:11:05 2010 @@ -538,6 +538,8 @@ argument = arguments_node.children[i] arg_type = argument.type if arg_type == syms.fpdef: + parenthesized = False + complex_args = False while True: if i + 1 < child_count and \ arguments_node.children[i + 1].type == tokens.EQUAL: @@ -546,13 +548,19 @@ i += 2 have_default = True elif have_default: - msg = "non-default argument follows default argument" + if parenthesized and not complex_args: + msg = "parenthesized arg with default" + else: + msg = ("non-default argument follows default " + "argument") self.error(msg, arguments_node) if len(argument.children) == 3: sub_arg = argument.children[1] if len(sub_arg.children) != 1: + complex_args = True args.append(self.handle_arg_unpacking(sub_arg)) else: + parenthesized = True argument = sub_arg.children[0] continue if argument.children[0].type == tokens.NAME: Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Fri Jun 25 17:11:05 2010 @@ -580,6 +580,9 @@ input = "def f(a=b, c): pass" exc = py.test.raises(SyntaxError, self.get_ast, input).value assert exc.msg == "non-default argument follows default argument" + input = "def f((x)=23): pass" + exc = py.test.raises(SyntaxError, self.get_ast, input).value + assert exc.msg == "parenthesized arg with default" def test_decorators(self): to_examine = (("def f(): pass", ast.FunctionDef), From benjamin at codespeak.net Fri Jun 25 17:24:28 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 17:24:28 +0200 (CEST) Subject: [pypy-svn] r75602 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100625152428.285BF282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 17:24:26 2010 New Revision: 75602 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Log: being nitpicky about error messages Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py Fri Jun 25 17:24:26 2010 @@ -116,7 +116,7 @@ try: misc.check_forbidden_name(name) except misc.ForbiddenNameAssignment, e: - self.error("assignment to %s" % (e.name,), node) + self.error("cannot assign to %s" % (e.name,), node) def set_context(self, expr, ctx): """Set the context of an expression to Store or Del if possible.""" @@ -125,7 +125,7 @@ except ast.UnacceptableExpressionContext, e: self.error_ast(e.msg, e.node) except misc.ForbiddenNameAssignment, e: - self.error_ast("assignment to %s" % (e.name,), e.node) + self.error_ast("cannot assign to %s" % (e.name,), e.node) def handle_print_stmt(self, print_node): dest = None Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py Fri Jun 25 17:24:26 2010 @@ -794,7 +794,7 @@ for template in invalid: input = template % (name,) exc = py.test.raises(SyntaxError, self.get_ast, input).value - assert exc.msg == "assignment to %s" % (name,) + assert exc.msg == "cannot assign to %s" % (name,) def test_lambda(self): lam = self.get_first_expr("lambda x: expr") From benjamin at codespeak.net Fri Jun 25 17:31:29 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 17:31:29 +0200 (CEST) Subject: [pypy-svn] r75603 - in pypy/branch/fast-forward/pypy/interpreter/astcompiler: . test Message-ID: <20100625153129.1DC9B282B9C@codespeak.net> Author: benjamin Date: Fri Jun 25 17:31:27 2010 New Revision: 75603 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Log: remove 'both' Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Fri Jun 25 17:31:27 2010 @@ -107,7 +107,7 @@ """Decide on the scope of a name.""" if flags & SYM_GLOBAL: if flags & SYM_PARAM: - err = "name '%s' is both local and global" % (name,) + err = "name '%s' is local and global" % (name,) raise SyntaxError(err, self.lineno, self.col_offset) self.symbols[name] = SCOPE_GLOBAL_EXPLICIT globs[name] = None Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_symtable.py Fri Jun 25 17:31:27 2010 @@ -269,7 +269,7 @@ assert xscp.lookup("y") == symtable.SCOPE_GLOBAL_EXPLICIT assert zscp.lookup("y") == symtable.SCOPE_FREE exc = py.test.raises(SyntaxError, self.func_scope, input).value - assert exc.msg == "name 'x' is both local and global" + assert exc.msg == "name 'x' is local and global" def test_optimization(self): assert not self.mod_scope("").can_be_optimized From fijal at codespeak.net Fri Jun 25 19:58:08 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jun 2010 19:58:08 +0200 (CEST) Subject: [pypy-svn] r75604 - pypy/trunk/pypy/tool/release Message-ID: <20100625175808.43E7B282BAD@codespeak.net> Author: fijal Date: Fri Jun 25 19:58:05 2010 New Revision: 75604 Modified: pypy/trunk/pypy/tool/release/make_release.py Log: Finish make_release.py Modified: pypy/trunk/pypy/tool/release/make_release.py ============================================================================== --- pypy/trunk/pypy/tool/release/make_release.py (original) +++ pypy/trunk/pypy/tool/release/make_release.py Fri Jun 25 19:58:05 2010 @@ -16,6 +16,8 @@ from pypy.tool.udir import udir from pypy.tool.release.package import package import tarfile +import os +import shutil BASEURL = 'http://buildbot.pypy.org/nightly/' @@ -47,28 +49,39 @@ to_download = browse_nightly(branch) tmpdir = udir.join('download') tmpdir.ensure(dir=True) - for (kind, platform), (rev, name) in to_download.iteritems(): - if platform == 'win32': - print 'Ignoring %s, windows unsupported' % name - else: - print "Downloading %s at rev %d" % (name, rev) - url = BASEURL + branch + "/" + name - data = urllib2.urlopen(url).read() - tmpdir.join(name).write(data, mode="wb") - t = tarfile.open(str(tmpdir.join(name))) - data = t.extractfile('pypy-c').read() - pypy_c = tmpdir.join('pypy-c') - pypy_c.write(data, mode="wb") - if kind == 'jit': - kind = '' + alltars = [] + try: + os.chdir(str(tmpdir)) + for (kind, platform), (rev, name) in to_download.iteritems(): + if platform == 'win32': + print 'Ignoring %s, windows unsupported' % name else: - kind = '-' + kind - name = 'pypy-%s%s-%s' % (release, kind, platform) - builddir = package(py.path.local(autopath.pypydir).join('..'), - name=name, - override_pypy_c=pypy_c) - print "Build %s/%s.tar.bz2" % (builddir, name) - print "\nLook into %s for packages" % builddir + print "Downloading %s at rev %d" % (name, rev) + url = BASEURL + branch + "/" + name + data = urllib2.urlopen(url).read() + tmpdir.join(name).write(data, mode="wb") + t = tarfile.open(str(tmpdir.join(name))) + dirname = t.getmembers()[0].name + t.extractall(path=str(tmpdir)) + os.system('mv %s %s' % (str(tmpdir.join(dirname)), + str(tmpdir.join('pypy-%s' % release)))) + if kind == 'jit': + kind = '' + else: + kind = '-' + kind + olddir = os.getcwd() + name = 'pypy-%s-%s%s.tar.bz2' % (release, platform, kind) + print "Building %s" % name + t = tarfile.open(name, 'w:bz2') + t.add('pypy-%s' % release) + alltars.append(name) + t.close() + shutil.rmtree(str(tmpdir.join('pypy-1.3'))) + for name in alltars: + print "Uploading %s" % name + os.system('scp %s codespeak.net:/www/pypy.org/htdocs/download' % name) + finally: + os.chdir(olddir) if __name__ == '__main__': if len(sys.argv) != 2: From benjamin at codespeak.net Fri Jun 25 21:40:54 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 21:40:54 +0200 (CEST) Subject: [pypy-svn] r75605 - in pypy/branch/fast-forward/pypy/interpreter: . test Message-ID: <20100625194054.3BD0D282BAD@codespeak.net> Author: benjamin Date: Fri Jun 25 21:40:50 2010 New Revision: 75605 Modified: pypy/branch/fast-forward/pypy/interpreter/nestedscope.py pypy/branch/fast-forward/pypy/interpreter/test/test_nestedscope.py Log: prevent locals() from leaking outer scopes into classes Modified: pypy/branch/fast-forward/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/nestedscope.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/nestedscope.py Fri Jun 25 21:40:50 2010 @@ -2,6 +2,7 @@ from pypy.interpreter import function, pycode, pyframe from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.mixedmodule import MixedModule +from pypy.interpreter.astcompiler import consts from pypy.rlib import jit from pypy.tool.uid import uid @@ -122,7 +123,9 @@ super_fast2locals(self) # cellvars are values exported to inner scopes # freevars are values coming from outer scopes - freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars + freevarnames = self.pycode.co_cellvars + if self.pycode.co_flags & consts.CO_OPTIMIZED: + freevarnames.extend(self.pycode.co_freevars) for i in range(len(freevarnames)): name = freevarnames[i] cell = self.cells[i] Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_nestedscope.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/test/test_nestedscope.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/test/test_nestedscope.py Fri Jun 25 21:40:50 2010 @@ -79,3 +79,13 @@ g = f() raises(ValueError, "g.func_closure[0].cell_contents") + + def test_leaking_class_locals(self): + def f(x): + class X: + x = 12 + def f(self): + return x + locals() + return X + assert f(1).x == 12 From benjamin at codespeak.net Fri Jun 25 21:46:43 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 21:46:43 +0200 (CEST) Subject: [pypy-svn] r75606 - pypy/branch/fast-forward/pypy/interpreter/astcompiler Message-ID: <20100625194643.64F9236C227@codespeak.net> Author: benjamin Date: Fri Jun 25 21:46:41 2010 New Revision: 75606 Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Log: typo Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/symtable.py Fri Jun 25 21:46:41 2010 @@ -89,7 +89,7 @@ self.has_exec = True def note_import_star(self, imp): - """Called when a start import is found.""" + """Called when a star import is found.""" pass def mangle(self, name): From benjamin at codespeak.net Fri Jun 25 22:18:38 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 22:18:38 +0200 (CEST) Subject: [pypy-svn] r75607 - in pypy/branch/fast-forward/pypy/module/__builtin__: . test Message-ID: <20100625201838.7E94036C536@codespeak.net> Author: benjamin Date: Fri Jun 25 22:18:36 2010 New Revision: 75607 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Log: give enumerate a start argument Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Fri Jun 25 22:18:36 2010 @@ -374,10 +374,11 @@ self.w_iter = w_iter self.w_index = w_start - def descr___new__(space, w_subtype, w_iterable): + def descr___new__(space, w_subtype, w_iterable, start=0): self = space.allocate_instance(W_Enumerate, w_subtype) - self.__init__(space.iter(w_iterable), space.wrap(0)) + self.__init__(space.iter(w_iterable), space.wrap(start)) return space.wrap(self) + descr___new__.unwrap_spec = [ObjSpace, W_Root, W_Root, int] def descr___iter__(self, space): return space.wrap(self) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_builtin.py Fri Jun 25 22:18:36 2010 @@ -186,7 +186,8 @@ raises(StopIteration, enum.next) raises(TypeError, enumerate, 1) raises(TypeError, enumerate, None) - + enum = enumerate(range(5), 2) + assert list(enum) == zip(range(2, 7), range(5)) def test_xrange_args(self): ## # xrange() attributes are deprecated and were removed in Python 2.3. From benjamin at codespeak.net Fri Jun 25 22:23:55 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 22:23:55 +0200 (CEST) Subject: [pypy-svn] r75608 - pypy/branch/fast-forward/pypy/module/__builtin__ Message-ID: <20100625202355.E533E36C536@codespeak.net> Author: benjamin Date: Fri Jun 25 22:23:54 2010 New Revision: 75608 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Log: avoid rewrapping integers Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Fri Jun 25 22:23:54 2010 @@ -374,11 +374,12 @@ self.w_iter = w_iter self.w_index = w_start - def descr___new__(space, w_subtype, w_iterable, start=0): + def descr___new__(space, w_subtype, w_iterable, w_start=None): self = space.allocate_instance(W_Enumerate, w_subtype) - self.__init__(space.iter(w_iterable), space.wrap(start)) + if w_start is None: + w_start = space.wrap(0) + self.__init__(space.iter(w_iterable), w_start) return space.wrap(self) - descr___new__.unwrap_spec = [ObjSpace, W_Root, W_Root, int] def descr___iter__(self, space): return space.wrap(self) From benjamin at codespeak.net Fri Jun 25 22:33:11 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 22:33:11 +0200 (CEST) Subject: [pypy-svn] r75609 - pypy/branch/fast-forward/pypy/module/__builtin__ Message-ID: <20100625203311.5AF08282BAD@codespeak.net> Author: benjamin Date: Fri Jun 25 22:33:10 2010 New Revision: 75609 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Log: start must be an index Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Fri Jun 25 22:33:10 2010 @@ -374,10 +374,12 @@ self.w_iter = w_iter self.w_index = w_start - def descr___new__(space, w_subtype, w_iterable, w_start=None): + def descr___new__(space, w_subtype, w_iterable, w_start=NoneNotWrapped): self = space.allocate_instance(W_Enumerate, w_subtype) if w_start is None: w_start = space.wrap(0) + else: + w_start = space.index(w_start) self.__init__(space.iter(w_iterable), w_start) return space.wrap(self) From benjamin at codespeak.net Fri Jun 25 23:27:31 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 25 Jun 2010 23:27:31 +0200 (CEST) Subject: [pypy-svn] r75610 - in pypy/branch/fast-forward/pypy/module/__builtin__: . test Message-ID: <20100625212731.03046282BAD@codespeak.net> Author: benjamin Date: Fri Jun 25 23:27:30 2010 New Revision: 75610 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py Log: __reversed__ on classic classes Modified: pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/interp_classobj.py Fri Jun 25 23:27:30 2010 @@ -670,7 +670,7 @@ rawdict = {} # unary operations -for op in "neg pos abs invert int long float oct hex enter".split(): +for op in "neg pos abs invert int long float oct hex enter reversed".split(): specialname = "__%s__" % (op, ) # fool the gateway logic by giving it a real unbound method meth = new.instancemethod( Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_classobj.py Fri Jun 25 23:27:30 2010 @@ -780,6 +780,12 @@ assert a == 23 assert c.got_exit + def test_reverse(self): + class X: + def __reversed__(self): + return [1, 2] + assert reversed(X()) == [1, 2] + class AppTestOldStyleSharing(AppTestOldstyle): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) From fijal at codespeak.net Fri Jun 25 23:33:07 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jun 2010 23:33:07 +0200 (CEST) Subject: [pypy-svn] r75611 - in pypy/extradoc/pypy.org: . source Message-ID: <20100625213307.CEBE0282BAD@codespeak.net> Author: fijal Date: Fri Jun 25 23:33:06 2010 New Revision: 75611 Modified: pypy/extradoc/pypy.org/compat.html pypy/extradoc/pypy.org/download.html pypy/extradoc/pypy.org/features.html pypy/extradoc/pypy.org/index.html pypy/extradoc/pypy.org/source/README pypy/extradoc/pypy.org/source/compat.txt pypy/extradoc/pypy.org/source/download.txt pypy/extradoc/pypy.org/source/features.txt pypy/extradoc/pypy.org/source/index.txt Log: Update to pypy 1.3 Modified: pypy/extradoc/pypy.org/compat.html ============================================================================== --- pypy/extradoc/pypy.org/compat.html (original) +++ pypy/extradoc/pypy.org/compat.html Fri Jun 25 23:33:06 2010 @@ -51,18 +51,26 @@ language, passing Python test suite (with minor modifications that were already accepted in the main python in newer versions). It supports most of the commonly used Python standard library modules; details below.

-

PyPy does not support the CPython C API, which means that third party -libraries for python, written in C, will not work.

-

Note: PyPy trunk has experimental support for CPython extension modules -in the trunk, however it was not released yet so downloads below won't have -it.

+

PyPy have alpha-level support of the CPython C API, however, as of 1.3 +release this feature is not yet complete. Most libraries would require +a bit of effort to work, but there are known success stories. Check out +PyPy blog for updates.

+

C extensions has to be recompiled for PyPy in order to work. Depending on +your build system, it might work out of the box or will be slightly harder. +In order to instruct pypy to load a CPython extension (compiled with supplied +Python.h), run following line:

+
+import cpyext
+
+

before importing an extensions. You can put this line in your PYTHONSTARTUP +file if you want this to be enabled permanently.

Standard library modules supported by PyPy, in alphabetical order:

    -
  • __builtin__ __pypy__ _codecs _lsprof _minimal_curses _random _rawffi _socket _sre _weakref bz2 cStringIO crypt errno exceptions fcntl gc itertools marshal math md5 mmap operator parser posix pyexpat select sha signal struct symbol sys termios thread time token unicodedata zipimport zlib
  • +
  • __builtin__ __pypy__ _codecs _lsprof _minimal_curses _random _rawffi _socket _sre _weakref bz2 cStringIO crypt errno exceptions fcntl gc itertools marshal math md5 mmap operator parser posix pyexpat select sha signal struct symbol sys termios thread time token unicodedata zipimport zlib

Supported, but written in pure-python:

    -
  • array binascii cPickle cmath collections ctypes datetime functools grp md5 pwd pyexpat sha sqlite3 syslog
  • +
  • array binascii cPickle cmath collections ctypes datetime functools grp md5 pwd pyexpat sha sqlite3 syslog

All modules that are pure python in CPython of course work.

Python libraries known to work under PyPy (the list is not exhaustive):

@@ -82,16 +90,16 @@
open("filename", "w").write("stuff")

The proper fix is

f = open("filename", "w")
f.write("stuff")
f.close()
-

or using the with keyword

+

or using the with keyword

with open("filename", "w") as f:
f.write("stuff")
  • We don't support certain attributes that were decided to be -implementation-dependent. For example, gc.get_referrers does not exist. -Others may have different behavior; for example, gc.enable and -gc.disable are supported, but they don't enable and disable the GC, but +implementation-dependent. For example, gc.get_referrers does not exist. +Others may have different behavior; for example, gc.enable and +gc.disable are supported, but they don't enable and disable the GC, but instead just enable and disable the running of finalizers.

  • -
  • You can't attach a __del__ method to a class after its creation.

    +
  • You can't attach a __del__ method to a class after its creation.

  • You can't store non-string keys in type objects. Example

    class A(object):
    locals()[42] = 3
    Modified: pypy/extradoc/pypy.org/download.html ============================================================================== --- pypy/extradoc/pypy.org/download.html (original) +++ pypy/extradoc/pypy.org/download.html Fri Jun 25 23:33:06 2010 @@ -47,8 +47,10 @@

    Download and install

    -

    Here are the various binaries of PyPy 1.2 that we provide for x86 Linux, -Mac OS/X or Windows. This is the first release of PyPy containing +

    Here are the various binaries of PyPy 1.3 that we provide for x86 Linux, +Mac OS/X or Windows. This release improves over 1.2 in terms of stability +of the JIT. It also

    +

    This is the first release of PyPy containing a JIT compiler, hence the main goal is to try this out and see how it works for you. We put a lot of effort into making the JIT a stable piece of software and we don't @@ -71,9 +73,9 @@ them do, nowadays), as well as on any x86-64 machine in the 32-bit compatibility mode.

    If your CPU is really old, it may not have SSE2. In this case, you need to translate yourself with the option --jit-backend=x86-without-sse2.

    @@ -82,7 +84,7 @@

    If you want to help us with implementing the 64-bit JIT backend, contact us!

    -
    +

    “No JIT” version

    WARNING! Unless you really want to try this out, we recommend the JIT version.

    @@ -93,9 +95,10 @@ binaries work on 32-bit x86 (IA-32) CPUs as well as x86-64 CPUs in the 32-bit compatibility mode.

    If your CPU is a 64-bit machine and you want to translate a 32-bit version of PyPy yourself, here are hints.

    @@ -122,16 +125,17 @@

    The Windows and the native 64-bit versions both need testing and careful reviewing; contact us!

    -
    +

    “Stackless” version

    Provides Stackless extensions, as well as greenlets. These binaries work on 32-bit x86 (IA-32) CPUs as well as x86-64 CPUs in the 32-bit compatibility mode.

    +
    +

    System Message: WARNING/2 ([dynamic-text], line 124)

    +Bullet list ends without a blank line; unexpected unindent.

    It is not possible right now to combine Stackless features with the JIT.

    If your CPU is a 64-bit machine and you want to translate a 32-bit version of PyPy yourself, here are hints.

    @@ -139,15 +143,15 @@

    Installing

    -

    All versions are packaged in a tar.bz2 or zip file. When +

    All versions are packaged in a tar.bz2 or zip file. When uncompressed, they run in-place. On Linux or Mac OS/X, they can also be installed by manually moving the files:

     /usr/bin/pypy     # or pypy-nojit etc.
    -/usr/share/pypy-1.2/lib-python/*
    -/usr/share/pypy-1.2/pypy/*
    +/usr/share/pypy-1.3/lib-python/*
    +/usr/share/pypy-1.3/pypy/*
     
    -

    You can also install it to /usr/local/bin and /usr/local/share.

    +

    You can also install it to /usr/local/bin and /usr/local/share.

    Building from source

    @@ -155,8 +159,8 @@
  • Get the source code. The following packages contain the source at the same revision as the above binaries (these are svn exports):

    Or you can checkout the current trunk using Subversion (the trunk usually works and is of course more up-to-date):

    @@ -167,12 +171,12 @@ The trunk version contains fixes to support MinGW32. More information on our dev site.

  • -
  • Enter the goal directory:

    +
  • Enter the goal directory:

     cd pypy-trunk/pypy/translator/goal
     
  • -
  • Run the translate.py script. Here are the common combinations +

  • Run the translate.py script. Here are the common combinations of options:

     python translate.py -Ojit                # get the JIT version
    @@ -189,7 +193,7 @@
     
     

    Note on building a 32-bit version on 64-bit systems

    -

    To build 32-bit versions of pypy-c you need to run translate.py +

    To build 32-bit versions of pypy-c you need to run translate.py in a 32-bit version of Python. You can check with:

     $ python
    
    Modified: pypy/extradoc/pypy.org/features.html
    ==============================================================================
    --- pypy/extradoc/pypy.org/features.html	(original)
    +++ pypy/extradoc/pypy.org/features.html	Fri Jun 25 23:33:06 2010
    @@ -47,13 +47,13 @@
     

    Features

    -

    PyPy 1.2 implements Python 2.5. It supports all of the core +

    PyPy 1.3 implements Python 2.5. It supports all of the core language, passing the Python test suite (with minor modifications that were already accepted in the main python in newer versions). It supports most of the commonly used Python standard library modules. For known differences with CPython, see our compatibility page. If you are interested in helping with 2.6, 2.7 or 3.x features, contact us!

    -

    PyPy 1.2 runs essentially only on Intel x86 (IA-32). On 64-bit platforms +

    PyPy 1.3 runs essentially only on Intel x86 (IA-32). On 64-bit platforms you have to use the 32-bit compatibility mode, for now — or contact us to help!

    @@ -86,10 +86,10 @@ cp untrusted.py virtualtmp/ pypy_interact.py --tmp=virtualtmp pypy-sandbox /tmp/untrusted.py
    -

    Note that the path /tmp/untrusted.py is a path inside the sandboxed -filesystem. You don't have to put untrusted.py in the real /tmp +

    Note that the path /tmp/untrusted.py is a path inside the sandboxed +filesystem. You don't have to put untrusted.py in the real /tmp directory at all.

    -

    To read more about its features, try pypy_interact.py --help or go to +

    To read more about its features, try pypy_interact.py --help or go to our dev site.

    Modified: pypy/extradoc/pypy.org/index.html ============================================================================== --- pypy/extradoc/pypy.org/index.html (original) +++ pypy/extradoc/pypy.org/index.html Fri Jun 25 23:33:06 2010 @@ -62,7 +62,7 @@
  • As well as other features.
  • -

    Download and try out the PyPy release 1.2!

    +

    Download and try out the PyPy release 1.3!

    To read more about Python, look into Python docs and check our Compatibility page. PyPy can run such python libraries as twisted and django and supports ctypes.

    Modified: pypy/extradoc/pypy.org/source/README ============================================================================== --- pypy/extradoc/pypy.org/source/README (original) +++ pypy/extradoc/pypy.org/source/README Fri Jun 25 23:33:06 2010 @@ -1,6 +1,6 @@ You generate this website by using yatiblog from here: -http://github.com/tav/ampify/blob/master/environ/startup/yatiblog +http://github.com/tav/ampify/blob/master/environ/yatiblog by running Modified: pypy/extradoc/pypy.org/source/compat.txt ============================================================================== --- pypy/extradoc/pypy.org/source/compat.txt (original) +++ pypy/extradoc/pypy.org/source/compat.txt Fri Jun 25 23:33:06 2010 @@ -8,14 +8,20 @@ already accepted in the main python in newer versions). It supports most of the commonly used Python `standard library modules`_; details below. -PyPy does not support the `CPython C API`_, which means that third party -libraries for python, written in C, will not work. +PyPy have alpha-level support of the `CPython C API`_, however, as of 1.3 +release this feature is not yet complete. Most libraries would require +a bit of effort to work, but there are known success stories. Check out +PyPy blog for updates. + +C extensions has to be recompiled for PyPy in order to work. Depending on +your build system, it might work out of the box or will be slightly harder. +In order to instruct pypy to load a CPython extension (compiled with supplied +Python.h), run following line:: -.. class:: download_menu + import cpyext - *Note*: PyPy trunk has *experimental* support for CPython extension modules - in the trunk, however it was not released yet so downloads below won't have - it. +before importing an extensions. You can put this line in your PYTHONSTARTUP +file if you want this to be enabled permanently. Standard library modules supported by PyPy, in alphabetical order: Modified: pypy/extradoc/pypy.org/source/download.txt ============================================================================== --- pypy/extradoc/pypy.org/source/download.txt (original) +++ pypy/extradoc/pypy.org/source/download.txt Fri Jun 25 23:33:06 2010 @@ -6,8 +6,11 @@ Download ============================================================ -Here are the various binaries of **PyPy 1.2** that we provide for x86 Linux, -Mac OS/X or Windows. This is the first release of PyPy containing +Here are the various binaries of **PyPy 1.3** that we provide for x86 Linux, +Mac OS/X or Windows. This release improves over 1.2 in terms of stability +of the JIT. It also + +This is the first release of PyPy containing a JIT compiler, hence the main goal is to try this out and see how it works for you. We put a lot of effort into making the JIT a stable piece of software and we don't @@ -37,11 +40,10 @@ * `Linux binary`__ * `Mac OS/X binary`__ -* `Windows binary`__ +* Windows binary - not yet ready -.. __: http://pypy.org/download/pypy-1.2-linux.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-osx.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-win32.zip +.. __: http://pypy.org/download/pypy-1.3-linux.tar.bz2 +.. __: http://pypy.org/download/pypy-1.3-osx.tar.bz2 If your CPU is really old, it may not have SSE2. In this case, you need to translate_ yourself with the option ``--jit-backend=x86-without-sse2``. @@ -71,11 +73,12 @@ * `Linux binary`__ * `Mac OS/X binary`__ -* `Windows binary`__ +* `Linux 64bit binary`__ +* Windows binary - not yet ready -.. __: http://pypy.org/download/pypy-1.2-linux-nojit.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-osx-nojit.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-win32-nojit.zip +.. __: http://pypy.org/download/pypy-1.3-linux-nojit.tar.bz2 +.. __: http://pypy.org/download/pypy-1.3-osx-nojit.tar.bz2 +.. __: http://pypy.org/download/pypy-1.3-linux64-nojit.tar.bz2 If your CPU is a 64-bit machine and you want to translate_ a 32-bit version of PyPy yourself, `here are hints`_. @@ -123,12 +126,7 @@ in the 32-bit compatibility mode. * `Linux binary`__ -* `Mac OS/X binary`__ -* `Windows binary`__ - -.. __: http://pypy.org/download/pypy-1.2-linux-stackless.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-osx-stackless.tar.bz2 -.. __: http://pypy.org/download/pypy-1.2-win32-stackless.zip +.. __: http://pypy.org/download/pypy-1.3-linux-stackless.tar.bz2 It is not possible right now to combine Stackless features with the JIT. @@ -146,8 +144,8 @@ installed by manually moving the files:: /usr/bin/pypy # or pypy-nojit etc. - /usr/share/pypy-1.2/lib-python/* - /usr/share/pypy-1.2/pypy/* + /usr/share/pypy-1.3/lib-python/* + /usr/share/pypy-1.3/pypy/* You can also install it to ``/usr/local/bin`` and ``/usr/local/share``. @@ -160,11 +158,11 @@ 1. Get the source code. The following packages contain the source at the same revision as the above binaries (these are svn exports): - * `pypy-1.2-src.tar.bz2`__ (sources, Unix line endings) - * `pypy-1.2-src.zip`__ (sources, Windows line endings) + * `pypy-1.3-src.tar.bz2`__ (sources, Unix line endings) + * `pypy-1.3-src.zip`__ (sources, Windows line endings) - .. __: http://pypy.org/download/pypy-1.2-src.tar.bz2 - .. __: http://pypy.org/download/pypy-1.2-src.zip + .. __: http://pypy.org/download/pypy-1.3-src.tar.bz2 + .. __: http://pypy.org/download/pypy-1.3-src.zip Or you can checkout the current trunk using Subversion_ (the trunk usually works and is of course more up-to-date):: @@ -235,6 +233,6 @@ .. _`sandboxing`: features.html#sandboxing .. _`stackless`: http://www.stackless.com/ .. _`greenlets`: http://codespeak.net/svn/greenlet/trunk/doc/greenlet.txt -.. _`pypy-1.2-src.tar.bz2`: release.html -.. _`pypy-1.2-src.zip`: release.html +.. _`pypy-1.3-src.tar.bz2`: release.html +.. _`pypy-1.3-src.zip`: release.html .. _Subversion: http://subversion.tigris.org/ Modified: pypy/extradoc/pypy.org/source/features.txt ============================================================================== --- pypy/extradoc/pypy.org/source/features.txt (original) +++ pypy/extradoc/pypy.org/source/features.txt Fri Jun 25 23:33:06 2010 @@ -6,14 +6,14 @@ PyPy features =========================================================== -**PyPy 1.2** implements **Python 2.5.** It supports all of the core +**PyPy 1.3** implements **Python 2.5.** It supports all of the core language, passing the Python test suite (with minor modifications that were already accepted in the main python in newer versions). It supports most of the commonly used Python standard library modules. For known differences with CPython, see our `compatibility`_ page. If you are interested in helping with 2.6, 2.7 or 3.x features, `contact us`_! -PyPy 1.2 runs essentially only on Intel `x86 (IA-32)`_. On 64-bit platforms +PyPy 1.3 runs essentially only on Intel `x86 (IA-32)`_. On 64-bit platforms you have to use the 32-bit compatibility mode, for now -- or `contact us`_ to help! Modified: pypy/extradoc/pypy.org/source/index.txt ============================================================================== --- pypy/extradoc/pypy.org/source/index.txt (original) +++ pypy/extradoc/pypy.org/source/index.txt Fri Jun 25 23:33:06 2010 @@ -22,7 +22,7 @@ .. class:: download -`Download and try out the PyPy release 1.2!`__ +`Download and try out the PyPy release 1.3!`__ .. __: download.html From fijal at codespeak.net Fri Jun 25 23:34:51 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jun 2010 23:34:51 +0200 (CEST) Subject: [pypy-svn] r75612 - pypy/extradoc/pypy.org/js Message-ID: <20100625213451.47B92282BAD@codespeak.net> Author: fijal Date: Fri Jun 25 23:34:49 2010 New Revision: 75612 Modified: pypy/extradoc/pypy.org/js/detect.js Log: Bumb number here as well Modified: pypy/extradoc/pypy.org/js/detect.js ============================================================================== --- pypy/extradoc/pypy.org/js/detect.js (original) +++ pypy/extradoc/pypy.org/js/detect.js Fri Jun 25 23:34:49 2010 @@ -2,13 +2,13 @@ $(document).ready(function() { var download_url, download_text; if (navigator.platform.indexOf('Linux') != -1) { - download_url = 'download/pypy-1.2-linux.tar.bz2'; + download_url = 'download/pypy-1.3-linux.tar.bz2'; download_text = 'Download linux x86 bin'; } else if (navigator.platform.indexOf('Win') != -1) { - download_url = 'download/pypy-1.2-win32.zip'; + download_url = 'download/pypy-1.3-win32.zip'; download_text = 'Download Windows x86 bin'; } else if (navigator.platform.indexOf('Mac') != 1) { - download_url = 'download/pypy-1.2-osx.tar.bz2'; + download_url = 'download/pypy-1.3-osx.tar.bz2'; downloat_text = 'Download Mac OS X 10.6 bin'; } else { download_url = "download.html"; From fijal at codespeak.net Fri Jun 25 23:37:29 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jun 2010 23:37:29 +0200 (CEST) Subject: [pypy-svn] r75613 - pypy/release/1.3.0 Message-ID: <20100625213729.0FD8D282BAD@codespeak.net> Author: fijal Date: Fri Jun 25 23:37:28 2010 New Revision: 75613 Added: pypy/release/1.3.0/ (props changed) - copied from r75612, pypy/release/1.3.x/ Log: what went as 1.3 release From fijal at codespeak.net Fri Jun 25 23:41:39 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jun 2010 23:41:39 +0200 (CEST) Subject: [pypy-svn] r75614 - in pypy/extradoc/pypy.org: . source Message-ID: <20100625214139.88F90282BAD@codespeak.net> Author: fijal Date: Fri Jun 25 23:41:38 2010 New Revision: 75614 Modified: pypy/extradoc/pypy.org/download.html pypy/extradoc/pypy.org/source/download.txt Log: Update download Modified: pypy/extradoc/pypy.org/download.html ============================================================================== --- pypy/extradoc/pypy.org/download.html (original) +++ pypy/extradoc/pypy.org/download.html Fri Jun 25 23:41:38 2010 @@ -50,11 +50,7 @@

    Here are the various binaries of PyPy 1.3 that we provide for x86 Linux, Mac OS/X or Windows. This release improves over 1.2 in terms of stability of the JIT. It also

    -

    This is the first release of PyPy containing -a JIT compiler, hence -the main goal is to try this out and see how it works for you. We put -a lot of effort into making the JIT a stable piece of software and we don't -observe crashes; however, please consider it a beta version to try things out.

    +

    Windows binaries are not ready yet

    • Download
      -

      System Message: WARNING/2 ([dynamic-text], line 124)

      +

      System Message: WARNING/2 ([dynamic-text], line 120)

      Bullet list ends without a blank line; unexpected unindent.

      It is not possible right now to combine Stackless features with the JIT.

      If your CPU is a 64-bit machine and you want to translate a 32-bit Modified: pypy/extradoc/pypy.org/source/download.txt ============================================================================== --- pypy/extradoc/pypy.org/source/download.txt (original) +++ pypy/extradoc/pypy.org/source/download.txt Fri Jun 25 23:41:38 2010 @@ -10,11 +10,7 @@ Mac OS/X or Windows. This release improves over 1.2 in terms of stability of the JIT. It also -This is the first release of PyPy containing -a JIT compiler, hence -the main goal is to try this out and see how it works for you. We put -a lot of effort into making the JIT a stable piece of software and we don't -observe crashes; however, please consider it a beta version to try things out. +**Windows binaries are not ready yet** .. class:: download_menu From agaynor at codespeak.net Fri Jun 25 23:44:56 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Fri, 25 Jun 2010 23:44:56 +0200 (CEST) Subject: [pypy-svn] r75615 - pypy/extradoc/pypy.org Message-ID: <20100625214456.59A86282BAD@codespeak.net> Author: agaynor Date: Fri Jun 25 23:44:55 2010 New Revision: 75615 Modified: pypy/extradoc/pypy.org/compat.html Log: A few grammar fixes Modified: pypy/extradoc/pypy.org/compat.html ============================================================================== --- pypy/extradoc/pypy.org/compat.html (original) +++ pypy/extradoc/pypy.org/compat.html Fri Jun 25 23:44:55 2010 @@ -51,18 +51,18 @@ language, passing Python test suite (with minor modifications that were already accepted in the main python in newer versions). It supports most of the commonly used Python standard library modules; details below.

      -

      PyPy have alpha-level support of the CPython C API, however, as of 1.3 -release this feature is not yet complete. Most libraries would require +

      PyPy has alpha-level support of the CPython C API, however, as of 1.3 +release this feature is not yet complete. Most libraries will require a bit of effort to work, but there are known success stories. Check out PyPy blog for updates.

      -

      C extensions has to be recompiled for PyPy in order to work. Depending on +

      C extensions need to be recompiled for PyPy in order to work. Depending on your build system, it might work out of the box or will be slightly harder. In order to instruct pypy to load a CPython extension (compiled with supplied Python.h), run following line:

       import cpyext
       
      -

      before importing an extensions. You can put this line in your PYTHONSTARTUP +

      before importing any extensions. You can put this line in your PYTHONSTARTUP file if you want this to be enabled permanently.

      Standard library modules supported by PyPy, in alphabetical order:

        @@ -131,4 +131,4 @@
    - \ No newline at end of file + From agaynor at codespeak.net Fri Jun 25 23:50:00 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Fri, 25 Jun 2010 23:50:00 +0200 (CEST) Subject: [pypy-svn] r75616 - pypy/extradoc/pypy.org/source Message-ID: <20100625215000.48659282BAD@codespeak.net> Author: agaynor Date: Fri Jun 25 23:49:58 2010 New Revision: 75616 Modified: pypy/extradoc/pypy.org/source/compat.txt Log: Make my changes in the source files. Modified: pypy/extradoc/pypy.org/source/compat.txt ============================================================================== --- pypy/extradoc/pypy.org/source/compat.txt (original) +++ pypy/extradoc/pypy.org/source/compat.txt Fri Jun 25 23:49:58 2010 @@ -8,19 +8,19 @@ already accepted in the main python in newer versions). It supports most of the commonly used Python `standard library modules`_; details below. -PyPy have alpha-level support of the `CPython C API`_, however, as of 1.3 -release this feature is not yet complete. Most libraries would require +PyPy has alpha-level support for the `CPython C API`_, however, as of 1.3 +release this feature is not yet complete. Most libraries will require a bit of effort to work, but there are known success stories. Check out PyPy blog for updates. -C extensions has to be recompiled for PyPy in order to work. Depending on +C extensions need to be recompiled for PyPy in order to work. Depending on your build system, it might work out of the box or will be slightly harder. In order to instruct pypy to load a CPython extension (compiled with supplied Python.h), run following line:: import cpyext -before importing an extensions. You can put this line in your PYTHONSTARTUP +before importing any extensions. You can put this line in your PYTHONSTARTUP file if you want this to be enabled permanently. Standard library modules supported by PyPy, in alphabetical order: From benjamin at codespeak.net Sat Jun 26 00:30:55 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sat, 26 Jun 2010 00:30:55 +0200 (CEST) Subject: [pypy-svn] r75617 - pypy/branch/fast-forward/pypy/module/__builtin__ Message-ID: <20100625223055.8403F282BAD@codespeak.net> Author: benjamin Date: Sat Jun 26 00:30:53 2010 New Revision: 75617 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Log: some dances for old style classes Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Sat Jun 26 00:30:53 2010 @@ -417,10 +417,16 @@ def reversed(space, w_sequence): """Return a iterator that yields items of sequence in reverse.""" - w_reversed_descr = space.lookup(w_sequence, "__reversed__") - if w_reversed_descr is None: - return space.wrap(W_ReversedIterator(space, w_sequence)) - return space.get_and_call_function(w_reversed_descr, w_sequence) + w_reversed = None + if space.is_oldstyle_instance(w_sequence): + w_reversed = space.findattr(w_sequence, space.wrap("__reversed__")) + else: + w_reversed_descr = space.lookup(w_sequence, "__reversed__") + if w_reversed_descr is not None: + w_reversed = space.get(w_reversed_descr, w_sequence) + if w_reversed is not None: + return space.call_function(w_reversed) + return space.wrap(W_ReversedIterator(space, w_sequence)) reversed.unwrap_spec = [ObjSpace, W_Root] class W_ReversedIterator(Wrappable): From benjamin at codespeak.net Sat Jun 26 01:01:31 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sat, 26 Jun 2010 01:01:31 +0200 (CEST) Subject: [pypy-svn] r75618 - pypy/branch/fast-forward/pypy/module/__builtin__ Message-ID: <20100625230131.15214282BAD@codespeak.net> Author: benjamin Date: Sat Jun 26 01:01:28 2010 New Revision: 75618 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Log: ensure reversed argument is a sequence Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Sat Jun 26 01:01:28 2010 @@ -433,6 +433,9 @@ def __init__(self, space, w_sequence): self.remaining = space.int_w(space.len(w_sequence)) - 1 + if space.lookup(w_sequence, "__getitem__") is None: + msg = "reversed() argument must be a sequence" + raise OperationError(space.w_TypeError, space.wrap(msg)) self.w_sequence = w_sequence def descr___iter__(self, space): From fijal at codespeak.net Sat Jun 26 01:24:14 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 01:24:14 +0200 (CEST) Subject: [pypy-svn] r75619 - pypy/trunk/pypy/doc Message-ID: <20100625232414.75F6536C22E@codespeak.net> Author: fijal Date: Sat Jun 26 01:24:12 2010 New Revision: 75619 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Add a random set of people Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Sat Jun 26 01:24:12 2010 @@ -39,3 +39,6 @@ * Various small improvements have been added to the JIT code, as well as a great speedup of compiling time. + +Cheers, +Maciej Fijalkowski, Armin Rigo, Alex Gaynor, Amaury Forgeot d'Arc and the PyPy team From fijal at codespeak.net Sat Jun 26 01:26:31 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 01:26:31 +0200 (CEST) Subject: [pypy-svn] r75620 - pypy/trunk/pypy/doc Message-ID: <20100625232631.F254F36C22E@codespeak.net> Author: fijal Date: Sat Jun 26 01:26:30 2010 New Revision: 75620 Modified: pypy/trunk/pypy/doc/release-1.3.0.txt Log: Use plural here Modified: pypy/trunk/pypy/doc/release-1.3.0.txt ============================================================================== --- pypy/trunk/pypy/doc/release-1.3.0.txt (original) +++ pypy/trunk/pypy/doc/release-1.3.0.txt Sat Jun 26 01:26:30 2010 @@ -13,8 +13,8 @@ stability, this feature is in alpha stage and it is not yet suited for production environments. -Highlight of this release -========================= +Highlights of this release +========================== * We introduced support for CPython extension modules written in C. As of now, this support is in alpha, and it's very unlikely unaltered C extensions will From agaynor at codespeak.net Sat Jun 26 01:28:07 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Sat, 26 Jun 2010 01:28:07 +0200 (CEST) Subject: [pypy-svn] r75621 - in pypy/trunk/pypy: rlib/rsre/test translator/c/gcc translator/c/src Message-ID: <20100625232807.189E536C22E@codespeak.net> Author: agaynor Date: Sat Jun 26 01:28:05 2010 New Revision: 75621 Modified: pypy/trunk/pypy/rlib/rsre/test/targetrsre.py pypy/trunk/pypy/translator/c/gcc/instruction.py pypy/trunk/pypy/translator/c/gcc/trackgcroot.py pypy/trunk/pypy/translator/c/src/mem.h Log: Add a shebang to targetrsre for convenience. Modified: pypy/trunk/pypy/rlib/rsre/test/targetrsre.py ============================================================================== --- pypy/trunk/pypy/rlib/rsre/test/targetrsre.py (original) +++ pypy/trunk/pypy/rlib/rsre/test/targetrsre.py Sat Jun 26 01:28:05 2010 @@ -1,3 +1,4 @@ +#!/usr/bin/env python from pypy.rlib.rarithmetic import intmask from pypy.rlib.rsre import rsre import os, time Modified: pypy/trunk/pypy/translator/c/gcc/instruction.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/instruction.py (original) +++ pypy/trunk/pypy/translator/c/gcc/instruction.py Sat Jun 26 01:28:05 2010 @@ -1,3 +1,5 @@ +import sys + LOC_REG = 0 LOC_ESP_PLUS = 1 LOC_EBP_PLUS = 2 Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Sat Jun 26 01:28:05 2010 @@ -17,6 +17,7 @@ class FunctionGcRootTracker(object): skip = 0 + COMMENT = "([#;].*)?" @classmethod def init_regexp(cls): @@ -25,10 +26,10 @@ cls.r_globllabel = re.compile(cls.LABEL+r"=[.][+]%d\s*$"%cls.OFFSET_LABELS) cls.r_insn = re.compile(r"\t([a-z]\w*)\s") - cls.r_unaryinsn = re.compile(r"\t[a-z]\w*\s+("+cls.OPERAND+")\s*$") + cls.r_unaryinsn = re.compile(r"\t[a-z]\w*\s+("+cls.OPERAND+")\s*" + cls.COMMENT + "$") cls.r_binaryinsn = re.compile(r"\t[a-z]\w*\s+(?P"+cls.OPERAND+"),\s*(?P"+cls.OPERAND+")\s*$") - cls.r_jump = re.compile(r"\tj\w+\s+"+cls.LABEL+"\s*$") + cls.r_jump = re.compile(r"\tj\w+\s+"+cls.LABEL+"\s*" + cls.COMMENT + "$") cls.r_jmp_switch = re.compile(r"\tjmp\t[*]"+cls.LABEL+"[(]") cls.r_jmp_source = re.compile(r"\d*[(](%[\w]+)[,)]") @@ -616,6 +617,9 @@ # tail-calls are equivalent to RET for us return InsnRet(self.CALLEE_SAVE_REGISTERS) return InsnStop() + + def visit_jmpl(self, *args, **kwargs): + return self.visit_jmp(*args, **kwargs) def register_jump_to(self, label): if not isinstance(self.insns[-1], InsnStop): Modified: pypy/trunk/pypy/translator/c/src/mem.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/mem.h (original) +++ pypy/trunk/pypy/translator/c/src/mem.h Sat Jun 26 01:28:05 2010 @@ -29,7 +29,7 @@ dependency that we want. */ #define pypy_asm_gcroot(p) ({void*_r; \ - asm ("/* GCROOT %0 */" : "=g" (_r) : \ + asm ("/* GCROOT %0 */" : "=r" (_r) : \ "0" (p), "m" (__gcnoreorderhack)); \ _r; }) From fijal at codespeak.net Sat Jun 26 01:30:19 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 01:30:19 +0200 (CEST) Subject: [pypy-svn] r75622 - pypy/trunk/pypy/module/sys Message-ID: <20100625233019.8F61F36C22E@codespeak.net> Author: fijal Date: Sat Jun 26 01:30:18 2010 New Revision: 75622 Modified: pypy/trunk/pypy/module/sys/version.py Log: Bumb version here, remove comment which seems to be out of date Modified: pypy/trunk/pypy/module/sys/version.py ============================================================================== --- pypy/trunk/pypy/module/sys/version.py (original) +++ pypy/trunk/pypy/module/sys/version.py Sat Jun 26 01:30:18 2010 @@ -7,8 +7,7 @@ CPYTHON_VERSION = (2, 5, 2, "beta", 42) CPYTHON_API_VERSION = 1012 -# when changing the pypy version, remind to also change the name of trunk/lib/pypyX.Y -PYPY_VERSION = (1, 2, 0, "beta", '?') +PYPY_VERSION = (1, 3, 0, "beta", '?') # the last item is replaced by the svn revision ^^^ TRIM_URL_UP_TO = 'svn/pypy/' From agaynor at codespeak.net Sat Jun 26 01:36:28 2010 From: agaynor at codespeak.net (agaynor at codespeak.net) Date: Sat, 26 Jun 2010 01:36:28 +0200 (CEST) Subject: [pypy-svn] r75623 - in pypy/trunk/pypy/translator/c: gcc src Message-ID: <20100625233628.D9E9B36C22E@codespeak.net> Author: agaynor Date: Sat Jun 26 01:36:27 2010 New Revision: 75623 Modified: pypy/trunk/pypy/translator/c/gcc/instruction.py pypy/trunk/pypy/translator/c/gcc/trackgcroot.py pypy/trunk/pypy/translator/c/src/mem.h Log: Rollback portions of r75621 that should not have landed. Modified: pypy/trunk/pypy/translator/c/gcc/instruction.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/instruction.py (original) +++ pypy/trunk/pypy/translator/c/gcc/instruction.py Sat Jun 26 01:36:27 2010 @@ -1,5 +1,3 @@ -import sys - LOC_REG = 0 LOC_ESP_PLUS = 1 LOC_EBP_PLUS = 2 Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Sat Jun 26 01:36:27 2010 @@ -618,9 +618,6 @@ return InsnRet(self.CALLEE_SAVE_REGISTERS) return InsnStop() - def visit_jmpl(self, *args, **kwargs): - return self.visit_jmp(*args, **kwargs) - def register_jump_to(self, label): if not isinstance(self.insns[-1], InsnStop): self.labels[label].previous_insns.append(self.insns[-1]) Modified: pypy/trunk/pypy/translator/c/src/mem.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/mem.h (original) +++ pypy/trunk/pypy/translator/c/src/mem.h Sat Jun 26 01:36:27 2010 @@ -29,7 +29,7 @@ dependency that we want. */ #define pypy_asm_gcroot(p) ({void*_r; \ - asm ("/* GCROOT %0 */" : "=r" (_r) : \ + asm ("/* GCROOT %0 */" : "=g" (_r) : \ "0" (p), "m" (__gcnoreorderhack)); \ _r; }) From fijal at codespeak.net Sat Jun 26 04:50:00 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 04:50:00 +0200 (CEST) Subject: [pypy-svn] r75624 - pypy/trunk/pypy/doc Message-ID: <20100626025000.350BA36C22E@codespeak.net> Author: fijal Date: Sat Jun 26 04:49:56 2010 New Revision: 75624 Modified: pypy/trunk/pypy/doc/index.txt Log: Bumb the number here as well Modified: pypy/trunk/pypy/doc/index.txt ============================================================================== --- pypy/trunk/pypy/doc/index.txt (original) +++ pypy/trunk/pypy/doc/index.txt Sat Jun 26 04:49:56 2010 @@ -8,7 +8,7 @@ Getting into PyPy ... ============================================= -* `Release 1.2`_: the latest official release +* `Release 1.3`_: the latest official release * `PyPy Blog`_: news and status info about PyPy @@ -56,4 +56,4 @@ .. _`Documentation`: docindex.html .. _`Getting Started`: getting-started.html .. _papers: extradoc.html -.. _`Release 1.2`: release-1.2.0.html +.. _`Release 1.3`: release-1.3.0.html From fijal at codespeak.net Sat Jun 26 04:56:11 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 04:56:11 +0200 (CEST) Subject: [pypy-svn] r75625 - pypy/trunk/pypy/doc/jit Message-ID: <20100626025611.5AB8936C22E@codespeak.net> Author: fijal Date: Sat Jun 26 04:56:08 2010 New Revision: 75625 Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt Log: Fix ReST Modified: pypy/trunk/pypy/doc/jit/pyjitpl5.txt ============================================================================== --- pypy/trunk/pypy/doc/jit/pyjitpl5.txt (original) +++ pypy/trunk/pypy/doc/jit/pyjitpl5.txt Sat Jun 26 04:56:08 2010 @@ -58,7 +58,7 @@ is replaced with a call to a function, maybe_compile_and_run in warmstate.py, that checks if current loop is "hot" and should be compiled. -Next, starting with the portal graph, codewriter/*.py converts the graphs of the +Next, starting with the portal graph, codewriter/\*.py converts the graphs of the interpreter into JIT bytecode. Since this bytecode is stored in the final binary, it's designed to be concise rather than fast. The bytecode codewriter doesn't "see" (what it sees is defined by the JIT's policy) every part of the From fijal at codespeak.net Sat Jun 26 05:03:22 2010 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jun 2010 05:03:22 +0200 (CEST) Subject: [pypy-svn] r75626 - pypy/trunk/pypy/doc Message-ID: <20100626030322.913E736C22F@codespeak.net> Author: fijal Date: Sat Jun 26 05:03:21 2010 New Revision: 75626 Modified: pypy/trunk/pypy/doc/index.txt Log: Point "latest release" to pypy.org/download.html Modified: pypy/trunk/pypy/doc/index.txt ============================================================================== --- pypy/trunk/pypy/doc/index.txt (original) +++ pypy/trunk/pypy/doc/index.txt Sat Jun 26 05:03:21 2010 @@ -56,4 +56,4 @@ .. _`Documentation`: docindex.html .. _`Getting Started`: getting-started.html .. _papers: extradoc.html -.. _`Release 1.3`: release-1.3.0.html +.. _`Release 1.3`: http://pypy.org/download.html From benjamin at codespeak.net Mon Jun 28 02:06:00 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 02:06:00 +0200 (CEST) Subject: [pypy-svn] r75627 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100628000600.85566282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 02:05:58 2010 New Revision: 75627 Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py pypy/branch/fast-forward/pypy/objspace/std/tupleobject.py pypy/branch/fast-forward/pypy/objspace/std/tupletype.py Log: add index and count methods to tuple Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_tupleobject.py Mon Jun 28 02:05:58 2010 @@ -328,6 +328,21 @@ assert repr((1,)) == '(1,)' assert repr(()) == '()' assert repr((1,2,3)) == '(1, 2, 3)' - + def test_getslice(self): assert ('a', 'b', 'c').__getslice__(-17, 2) == ('a', 'b') + + def test_count(self): + assert ().count(4) == 0 + assert (1, 2, 3, 4).count(3) == 1 + assert (1, 2, 3, 4).count(5) == 0 + assert (1, 1, 1).count(1) == 3 + + def test_index(self): + raises(ValueError, ().index, 4) + (1, 2).index(1) == 0 + (3, 4, 5).index(4) == 1 + raises(ValueError, (1, 2, 3, 4).index, 5) + assert (4, 2, 3, 4).index(4, 1) == 3 + assert (4, 4, 4).index(4, 1, 2) == 1 + raises(ValueError, (1, 2, 3, 4).index, 4, 0, 2) Modified: pypy/branch/fast-forward/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/tupleobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/tupleobject.py Mon Jun 28 02:05:58 2010 @@ -5,6 +5,7 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.rlib.rarithmetic import intmask from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice +from pypy.objspace.std import slicetype from pypy.interpreter import gateway from pypy.rlib.debug import make_sure_not_resized @@ -160,4 +161,31 @@ def getnewargs__Tuple(space, w_tuple): return space.newtuple([W_TupleObject(w_tuple.wrappeditems)]) -register_all(vars()) +def tuple_count__Tuple_ANY(space, w_tuple, w_obj): + count = 0 + for w_item in w_tuple.wrappeditems: + if space.eq_w(w_item, w_obj): + count += 1 + return space.wrap(count) + +def tuple_index__Tuple_ANY_ANY_ANY(space, w_tuple, w_obj, w_start, w_stop): + start = slicetype._Eval_SliceIndex(space, w_start) + stop = slicetype._Eval_SliceIndex(space, w_stop) + length = len(w_tuple.wrappeditems) + if start < 0: + start += length + if start < 0: + start = 0 + if stop < 0: + stop += length + if stop < 0: + stop = 0 + for i in range(start, min(stop, length)): + w_item = w_tuple.wrappeditems[i] + if space.eq_w(w_item, w_obj): + return space.wrap(i) + raise OperationError(space.w_ValueError, + space.wrap("tuple.index(x): x not in tuple")) + +from pypy.objspace.std import tupletype +register_all(vars(), tupletype) Modified: pypy/branch/fast-forward/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/tupletype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/tupletype.py Mon Jun 28 02:05:58 2010 @@ -1,5 +1,16 @@ +import sys from pypy.interpreter import gateway -from pypy.objspace.std.stdtypedef import StdTypeDef +from pypy.objspace.std.register_all import register_all +from pypy.objspace.std.stdtypedef import StdTypeDef, SMM + + +tuple_count = SMM("count", 2, + doc="count(obj) -> number of times obj appears in the tuple") + +tuple_index = SMM("index", 4, defaults=(0, sys.maxint), + doc="index(obj, [start, [stop]]) -> first index that obj " + "appears in the tuple") + def descr__new__(space, w_tupletype, w_sequence=gateway.NoneNotWrapped): from pypy.objspace.std.tupleobject import W_TupleObject @@ -23,3 +34,4 @@ If the argument is a tuple, the return value is the same object.''', __new__ = gateway.interp2app(descr__new__), ) +tuple_typedef.registermethods(globals()) From benjamin at codespeak.net Mon Jun 28 06:05:04 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 06:05:04 +0200 (CEST) Subject: [pypy-svn] r75628 - in pypy/branch/fast-forward/pypy: interpreter objspace/std Message-ID: <20100628040504.0196836C22E@codespeak.net> Author: benjamin Date: Mon Jun 28 06:05:03 2010 New Revision: 75628 Modified: pypy/branch/fast-forward/pypy/interpreter/typedef.py pypy/branch/fast-forward/pypy/objspace/std/typeobject.py pypy/branch/fast-forward/pypy/objspace/std/typetype.py Log: make doc an attribute for builtin types Modified: pypy/branch/fast-forward/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/typedef.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/typedef.py Mon Jun 28 06:05:03 2010 @@ -19,6 +19,7 @@ self.base = __base self.hasdict = '__dict__' in rawdict self.weakrefable = '__weakref__' in rawdict + self.doc = rawdict.pop('__doc__', None) if __base is not None: self.hasdict |= __base.hasdict self.weakrefable |= __base.weakrefable Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Mon Jun 28 06:05:03 2010 @@ -96,6 +96,7 @@ w_self.hasdict = False w_self.needsdel = False w_self.weakrefable = False + w_self.w_doc = space.w_None w_self.weak_subclasses = [] w_self.__flags__ = 0 # or _HEAPTYPE or _CPYTYPE w_self.instancetypedef = overridetypedef @@ -594,11 +595,12 @@ def setup_builtin_type(w_self): w_self.hasdict = w_self.instancetypedef.hasdict w_self.weakrefable = w_self.instancetypedef.weakrefable + w_self.w_doc = w_self.space.wrap(w_self.instancetypedef.doc) ensure_common_attributes(w_self) def ensure_common_attributes(w_self): ensure_static_new(w_self) - ensure_doc_attr(w_self) + w_self.dict_w.setdefault('__doc__', w_self.w_doc) if w_self.is_heaptype(): ensure_module_attr(w_self) w_self.mro_w = [] # temporarily @@ -612,10 +614,6 @@ if isinstance(w_new, Function): w_self.dict_w['__new__'] = StaticMethod(w_new) -def ensure_doc_attr(w_self): - # make sure there is a __doc__ in dict_w - w_self.dict_w.setdefault('__doc__', w_self.space.w_None) - def ensure_module_attr(w_self): # initialize __module__ in the dict (user-defined types only) if '__module__' not in w_self.dict_w: Modified: pypy/branch/fast-forward/pypy/objspace/std/typetype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typetype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typetype.py Mon Jun 28 06:05:03 2010 @@ -181,6 +181,8 @@ return space.wrap("""type(object) -> the object's type type(name, bases, dict) -> a new type""") w_type = _check(space, w_type) + if not w_type.is_heaptype(): + return w_type.w_doc w_result = w_type.getdictvalue(space, '__doc__') if w_result is None: return space.w_None From benjamin at codespeak.net Mon Jun 28 06:28:51 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 06:28:51 +0200 (CEST) Subject: [pypy-svn] r75629 - in pypy/branch/fast-forward/pypy/module/__builtin__: . test Message-ID: <20100628042851.D9FEA36C224@codespeak.net> Author: benjamin Date: Mon Jun 28 06:28:50 2010 New Revision: 75629 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_descriptor.py Log: add new property attributes (and cleanup hacks) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py Mon Jun 28 06:28:50 2010 @@ -101,11 +101,18 @@ self.w_fset = w_fset self.w_fdel = w_fdel self.w_doc = w_doc + self.getter_doc = False # our __doc__ comes from the getter if we don't have an explicit one - if space.is_w(self.w_doc, space.w_None): + if (space.is_w(self.w_doc, space.w_None) and + not space.is_w(self.w_fget, space.w_None)): w_getter_doc = space.findattr(self.w_fget, space.wrap("__doc__")) if w_getter_doc is not None: - self.w_doc = w_getter_doc + if type(self) is W_Property: + self.w_doc = w_getter_doc + else: + space.setattr(space.wrap(self), space.wrap("__doc__"), + w_getter_doc) + self.getter_doc = True init.unwrap_spec = ['self', ObjSpace, W_Root, W_Root, W_Root, W_Root] def new(space, w_subtype, w_fget=None, w_fset=None, w_fdel=None, w_doc=None): @@ -138,27 +145,31 @@ return space.w_None delete.unwrap_spec = ['self', ObjSpace, W_Root] - def getattribute(self, space, attr): - # XXX fixme: this is a workaround. It's hard but not impossible - # to have both a __doc__ on the 'property' type, and a __doc__ - # descriptor that can read the docstring of 'property' instances. - if attr == '__doc__': - return self.w_doc - # shortcuts - return space.call_function(object_getattribute(space), - space.wrap(self), space.wrap(attr)) - getattribute.unwrap_spec = ['self', ObjSpace, str] - - def setattr(self, space, attr, w_value): - # XXX kill me? This is mostly to make tests happy, raising - # a TypeError instead of an AttributeError and using "readonly" - # instead of "read-only" in the error message :-/ - if attr in ["__doc__", "fget", "fset", "fdel"]: - raise operationerrfmt(space.w_TypeError, - "Trying to set readonly attribute %s on property", attr) - return space.call_function(object_setattr(space), - space.wrap(self), space.wrap(attr), w_value) - setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] + def getter(self, space, w_getter): + return self._copy(space, w_getter=w_getter) + getter.unwrap_spec = ['self', ObjSpace, W_Root] + + def setter(self, space, w_setter): + return self._copy(space, w_setter=w_setter) + setter.unwrap_spec = ['self', ObjSpace, W_Root] + + def deleter(self, space, w_deleter): + return self._copy(space, w_deleter=w_deleter) + deleter.unwrap_spec = ['self', ObjSpace, W_Root] + + def _copy(self, space, w_getter=None, w_setter=None, w_deleter=None): + if w_getter is None: + w_getter = self.w_fget + if w_setter is None: + w_setter = self.w_fset + if w_deleter is None: + w_deleter = self.w_fdel + if self.getter_doc and w_getter is not None: + w_doc = space.w_None + else: + w_doc = self.w_doc + w_type = self.getclass(space) + return space.call_function(w_type, w_getter, w_setter, w_deleter, w_doc) W_Property.typedef = TypeDef( 'property', @@ -177,10 +188,15 @@ __get__ = interp2app(W_Property.get), __set__ = interp2app(W_Property.set), __delete__ = interp2app(W_Property.delete), - __getattribute__ = interp2app(W_Property.getattribute), - __setattr__ = interp2app(W_Property.setattr), fdel = interp_attrproperty_w('w_fdel', W_Property), fget = interp_attrproperty_w('w_fget', W_Property), fset = interp_attrproperty_w('w_fset', W_Property), + getter = interp2app(W_Property.getter), + setter = interp2app(W_Property.setter), + deleter = interp2app(W_Property.deleter), ) +# This allows us to have a __doc__ of the property type and a __doc__ descriptor +# for the instances. +W_Property.typedef.rawdict['__doc__'] = interp_attrproperty_w('w_doc', + W_Property) Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_descriptor.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_descriptor.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_descriptor.py Mon Jun 28 06:28:50 2010 @@ -325,3 +325,24 @@ X().x assert l + + def test_property_decorator(self): + class X(object): + @property + def x(self): + return 4 + @x.getter + def x(self): + return 2 + @x.setter + def x(self, new): + self.y = 42 + @x.deleter + def x(self): + self.z = 42 + x = X() + assert x.x == 2 + x.x = 32 + assert x.y == 42 + del x.x + assert x.z == 42 From hpk at codespeak.net Mon Jun 28 09:55:12 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 28 Jun 2010 09:55:12 +0200 (CEST) Subject: [pypy-svn] r75630 - in pypy/trunk/pypy: . translator/goal/test2 Message-ID: <20100628075512.1E5AF282B90@codespeak.net> Author: hpk Date: Mon Jun 28 09:55:10 2010 New Revision: 75630 Modified: pypy/trunk/pypy/conftest.py pypy/trunk/pypy/translator/goal/test2/test_app_main.py Log: remove redundant code and fix tests for running in PYTHONSTARTUP customized environments Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Mon Jun 28 09:55:10 2010 @@ -40,6 +40,13 @@ default="host", callback=_set_platform, help="set up tests to use specified platform as compile/run target") +def pytest_sessionstart(): + # have python subprocesses avoid startup customizations by default + try: + del os.environ['PYTHONSTARTUP'] + except KeyError: + pass + def pytest_funcarg__space(request): spaceconfig = getattr(request.cls, 'spaceconfig', {}) return gettestobjspace(**spaceconfig) Modified: pypy/trunk/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/trunk/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/trunk/pypy/translator/goal/test2/test_app_main.py Mon Jun 28 09:55:10 2010 @@ -8,19 +8,6 @@ banner = sys.version.splitlines()[0] -def relpath(path): - # force 'path' to be a relative path, for testing purposes - curdir = py.path.local() - p = py.path.local(path) - result = [] - while not p.relto(curdir): - result.append(os.pardir) - if curdir == curdir.dirpath(): - return str(path) # no relative path found, give up - curdir = curdir.dirpath() - result.append(p.relto(curdir)) - return os.path.join(*result) - app_main = os.path.join(autopath.this_dir, os.pardir, 'app_main.py') app_main = os.path.abspath(app_main) @@ -30,7 +17,8 @@ p = udir.join('demo_test_app_main_%d.py' % (_counter,)) _counter += 1 p.write(str(py.code.Source(source))) - return relpath(p) + # return relative path for testing purposes + return py.path.local().bestrelpath(p) demo_script = getscript(""" From antocuni at codespeak.net Mon Jun 28 10:49:54 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 28 Jun 2010 10:49:54 +0200 (CEST) Subject: [pypy-svn] r75631 - in pypy/trunk: lib-python/modified-2.5.2/distutils pypy/module/sys pypy/module/sys/test pypy/translator/goal/test2 Message-ID: <20100628084954.CAAF636C226@codespeak.net> Author: antocuni Date: Mon Jun 28 10:49:52 2010 New Revision: 75631 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/trunk/pypy/module/sys/state.py pypy/trunk/pypy/module/sys/test/test_initialpath.py pypy/trunk/pypy/translator/goal/test2/test_app_main.py Log: remove the possibility of putting the libraries in $PREFIX/lib/pypy1.3/*. It is too hard to keep in sync all the various tool that needs to know where the directories are, such as distutils, virtualenv, etc. Now the only supported hierarchy is the one adopted in the svn checkout (i.e., lib-python, lib_pypy and site-packages needs to be on some parent directory that the one where pypy-c resides) Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Mon Jun 28 10:49:52 2010 @@ -47,11 +47,7 @@ "calls to get_python_lib(standard_lib=1) cannot succeed") if prefix is None: prefix = PREFIX - pypylib = os.path.join(prefix, 'lib', 'pypy%d.%d' % sys.pypy_version_info[:2]) - if os.path.exists(pypylib): - return os.path.join(pypylib, 'site-packages') - else: - return os.path.join(prefix, 'site-packages') + return os.path.join(prefix, 'site-packages') _config_vars = None Modified: pypy/trunk/pypy/module/sys/state.py ============================================================================== --- pypy/trunk/pypy/module/sys/state.py (original) +++ pypy/trunk/pypy/module/sys/state.py Mon Jun 28 10:49:52 2010 @@ -32,30 +32,19 @@ if not stat.S_ISDIR(st[0]): raise OSError(errno.ENOTDIR, path) -def getinitialpath(prefix): - from pypy.module.sys.version import PYPY_VERSION - libdir = os.path.join(prefix, 'lib') - pypyxy_dir = os.path.join(libdir, 'pypy%d.%d' % PYPY_VERSION[:2]) - # search for the stdlib both in $PREFIX/lib/pypy1.2 and $PREFIX - for lib_prefix in [pypyxy_dir, prefix]: - try: - return get_importlist(lib_prefix) - except OSError: - pass - raise OSError # stdlib not foud -def get_importlist(lib_prefix): +def getinitialpath(prefix): from pypy.module.sys.version import CPYTHON_VERSION dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], CPYTHON_VERSION[1], CPYTHON_VERSION[2]) - lib_python = os.path.join(lib_prefix, 'lib-python') + lib_python = os.path.join(prefix, 'lib-python') python_std_lib = os.path.join(lib_python, dirname) checkdir(python_std_lib) python_std_lib_modified = os.path.join(lib_python, 'modified-' + dirname) checkdir(python_std_lib_modified) - lib_pypy = os.path.join(lib_prefix, 'lib_pypy') + lib_pypy = os.path.join(prefix, 'lib_pypy') checkdir(lib_pypy) importlist = [] Modified: pypy/trunk/pypy/module/sys/test/test_initialpath.py ============================================================================== --- pypy/trunk/pypy/module/sys/test/test_initialpath.py (original) +++ pypy/trunk/pypy/module/sys/test/test_initialpath.py Mon Jun 28 10:49:52 2010 @@ -12,21 +12,7 @@ return a, b, c -def test_stdlib_in_pypyxy(tmpdir): - pypyxy = tmpdir.join('lib', 'pypy%d.%d' % PYPY_VERSION[:2]) - dirs = build_hierarchy(pypyxy) - path = getinitialpath(str(tmpdir)) - assert path == map(str, dirs) - - def test_stdlib_in_prefix(tmpdir): dirs = build_hierarchy(tmpdir) path = getinitialpath(str(tmpdir)) assert path == map(str, dirs) - -def test_stdlib_precedence(tmpdir): - pypyxy = tmpdir.join('lib', 'pypy%d.%d' % PYPY_VERSION[:2]) - dirs1 = build_hierarchy(tmpdir) - dirs2 = build_hierarchy(pypyxy) - path = getinitialpath(str(tmpdir)) - assert path == map(str, dirs2) Modified: pypy/trunk/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/trunk/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/trunk/pypy/translator/goal/test2/test_app_main.py Mon Jun 28 10:49:52 2010 @@ -457,16 +457,14 @@ # setup code for test_get_library_path # ------------------------------------ from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION - libroot = 'lib/pypy%d.%d' % PYPY_VERSION[:2] cpy_ver = '%d.%d.%d' % CPYTHON_VERSION[:3] goal_dir = os.path.dirname(app_main) # build a directory hierarchy like which contains both bin/pypy-c and # lib/pypy1.2/* - prefix = udir.join('pathtest') + prefix = udir.join('pathtest').ensure(dir=1) fake_exe = prefix.join('bin/pypy-c').ensure(file=1) - pypyxy = prefix.join(libroot).ensure(dir=1) - expected_path = [str(pypyxy.join(subdir).ensure(dir=1)) + expected_path = [str(prefix.join(subdir).ensure(dir=1)) for subdir in ('lib_pypy', 'lib-python/modified-%s' % cpy_ver, 'lib-python/%s' % cpy_ver)] From afa at codespeak.net Mon Jun 28 13:46:45 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 28 Jun 2010 13:46:45 +0200 (CEST) Subject: [pypy-svn] r75632 - in pypy/branch/interplevel-codecs/pypy: module/_codecs module/_codecs/test rlib Message-ID: <20100628114645.2B818282B9D@codespeak.net> Author: afa Date: Mon Jun 28 13:46:43 2010 New Revision: 75632 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: Port some codecs from applevel to interplevel: raw_unicode_escape, and the error handlers Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Mon Jun 28 13:46:43 2010 @@ -9,8 +9,6 @@ 'charmap_encode' : 'app_codecs.charmap_encode', 'escape_decode' : 'app_codecs.escape_decode', 'escape_encode' : 'app_codecs.escape_encode', - 'raw_unicode_escape_decode' : 'app_codecs.raw_unicode_escape_decode', - 'raw_unicode_escape_encode' : 'app_codecs.raw_unicode_escape_encode', 'unicode_escape_decode' : 'app_codecs.unicode_escape_decode', 'unicode_escape_encode' : 'app_codecs.unicode_escape_encode', 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', @@ -44,6 +42,8 @@ 'charbuffer_encode': 'interp_codecs.buffer_encode', 'readbuffer_encode': 'interp_codecs.buffer_encode', 'charmap_decode' : 'interp_codecs.charmap_decode', + 'raw_unicode_escape_decode' : 'interp_codecs.raw_unicode_escape_decode', + 'raw_unicode_escape_encode' : 'interp_codecs.raw_unicode_escape_encode', } def __init__(self, space, *args): Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Mon Jun 28 13:46:43 2010 @@ -46,13 +46,6 @@ v = s[1:-1] return v, len(v) -def raw_unicode_escape_decode( data, errors='strict'): - """None - """ - res = PyUnicode_DecodeRawUnicodeEscape(data, len(data), errors) - res = u''.join(res) - return res, len(data) - def utf_7_decode( data, errors='strict'): """None """ @@ -205,13 +198,6 @@ res = ''.join(res) return res, len(res) -def raw_unicode_escape_encode( obj, errors='strict'): - """None - """ - res = PyUnicode_EncodeRawUnicodeEscape(obj, len(obj)) - res = ''.join(res) - return res, len(res) - # ---------------------------------------------------------------------- ##import sys @@ -690,30 +676,6 @@ p += ch return p -def PyUnicode_EncodeRawUnicodeEscape(s, size): - - if (size == 0): - return '' - - p = [] - for ch in s: -# /* Map 32-bit characters to '\Uxxxxxxxx' */ - if (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x' % (ord(ch)) - elif (ord(ch) >= 256) : -# /* Map 16-bit characters to '\uxxxx' */ - p += '\\' - p += 'u' - p += '%04x' % (ord(ch)) -# /* Copy everything else as-is */ - else: - p += chr(ord(ch)) - - #p += '\0' - return p - def charmapencode_output(c, mapping): rep = mapping[c] @@ -761,85 +723,6 @@ return res -def PyUnicode_DecodeRawUnicodeEscape(s, size, errors): - import sys - - if (size == 0): - return u'' - pos = 0 - p = [] - while (pos < len(s)): - ch = s[pos] - #/* Non-escape characters are interpreted as Unicode ordinals */ - if (ch != '\\'): - p += unichr(ord(ch)) - pos += 1 - continue - startinpos = pos -## /* \u-escapes are only interpreted iff the number of leading -## backslashes is odd */ - bs = pos - while pos < size: - if (s[pos] != '\\'): - break - p += unichr(ord(s[pos])) - pos += 1 - - # we have a backlash at the end of the string, stop here - if pos >= size: - break - - if (((pos - bs) & 1) == 0 or - pos >= size or - (s[pos] != 'u' and s[pos] != 'U')) : - p += unichr(ord(s[pos])) - pos += 1 - continue - - p.pop(-1) - if s[pos] == 'u': - count = 4 - else: - count = 8 - pos += 1 - - #/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ - x = 0 - try: - x = int(s[pos:pos+count], 16) - except ValueError: - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "truncated \\uXXXX", - s, size, pos, pos+count) - p += res[0] - pos = res[1] - else: - #ifndef Py_UNICODE_WIDE - if sys.maxunicode > 0xffff: - if (x > sys.maxunicode): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = res[1] - p += res[0] - else: - p += unichr(x) - pos += count - else: - if (x > 0x10000): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = res[1] - p += res[0] - - #endif - else: - p += unichr(x) - pos += count - - return p - def charmap_build(somestring): m = {} num = 0 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Mon Jun 28 13:46:43 2010 @@ -1,5 +1,5 @@ from pypy.interpreter.error import OperationError, operationerrfmt -from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, applevel +from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, interp2app from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy.rlib.objectmodel import we_are_translated @@ -114,78 +114,124 @@ "unknown encoding: %s", encoding) lookup_codec.unwrap_spec = [ObjSpace, str] -app_errors = applevel(""" -def check_exception(exc): +# ____________________________________________________________ +# Register standard error handlers + +def check_exception(space, w_exc): try: - delta = exc.end - exc.start - if delta < 0 or not isinstance(exc.object, (unicode, str)): - raise TypeError("wrong exception") - except AttributeError: - raise TypeError("wrong exception") - -def strict_errors(exc): - if isinstance(exc, Exception): - raise exc - else: - raise TypeError("codec must pass exception instance") - -def ignore_errors(exc): - check_exception(exc) - if isinstance(exc, UnicodeEncodeError): - return u'', exc.end - elif isinstance(exc, (UnicodeDecodeError, UnicodeTranslateError)): - return u'', exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -Py_UNICODE_REPLACEMENT_CHARACTER = u"\ufffd" - -def replace_errors(exc): - check_exception(exc) - if isinstance(exc, UnicodeEncodeError): - return u'?'*(exc.end-exc.start), exc.end - elif isinstance(exc, (UnicodeTranslateError, UnicodeDecodeError)): - return Py_UNICODE_REPLACEMENT_CHARACTER*(exc.end-exc.start), exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -def xmlcharrefreplace_errors(exc): - if isinstance(exc, UnicodeEncodeError): - res = [] - for ch in exc.object[exc.start:exc.end]: - res += '&#' - res += str(ord(ch)) - res += ';' - return u''.join(res), exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) - -def backslashreplace_errors(exc): - if isinstance(exc, UnicodeEncodeError): - p = [] - for c in exc.object[exc.start:exc.end]: - p += '\\\\' - oc = ord(c) - if (oc >= 0x00010000): - p += 'U' - p += "%.8x" % ord(c) + w_start = space.getattr(w_exc, space.wrap('start')) + w_end = space.getattr(w_exc, space.wrap('end')) + w_obj = space.getattr(w_exc, space.wrap('object')) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + raise OperationError(space.w_TypeError, space.wrap( + "wrong exception")) + + delta = space.int_w(w_end) - space.int_w(w_start) + if delta < 0 or not (space.isinstance_w(w_obj, space.w_str) or + space.isinstance_w(w_obj, space.w_unicode)): + raise OperationError(space.w_TypeError, space.wrap( + "wrong exception")) + +def strict_errors(space, w_exc): + check_exception(space, w_exc) + if space.isinstance_w(w_exc, space.w_BaseException): + raise OperationError(space.type(w_exc), w_exc) + else: + raise OperationError(space.w_TypeError, space.wrap( + "codec must pass exception instance")) + +def ignore_errors(space, w_exc): + check_exception(space, w_exc) + w_end = space.getattr(w_exc, space.wrap('end')) + if space.isinstance_w(w_exc, space.w_UnicodeEncodeError): + return space.newtuple([space.wrap(''), w_end]) + elif (space.isinstance_w(w_exc, space.w_UnicodeDecodeError) or + space.isinstance_w(w_exc, space.w_UnicodeTranslateError)): + return space.newtuple([space.wrap(u''), w_end]) + else: + typename = space.type(w_exc).getname(space, '?') + raise operationerrfmt(space.w_TypeError, + "don't know how to handle %s in error callback", typename) + +def replace_errors(space, w_exc): + check_exception(space, w_exc) + w_start = space.getattr(w_exc, space.wrap('start')) + w_end = space.getattr(w_exc, space.wrap('end')) + size = space.int_w(w_end) - space.int_w(w_start) + if space.isinstance_w(w_exc, space.w_UnicodeEncodeError): + text = '?' * size + return space.newtuple([space.wrap(text), w_end]) + elif (space.isinstance_w(w_exc, space.w_UnicodeDecodeError) or + space.isinstance_w(w_exc, space.w_UnicodeTranslateError)): + text = u'\ufffd' * size + return space.newtuple([space.wrap(text), w_end]) + else: + typename = space.type(w_exc).getname(space, '?') + raise operationerrfmt(space.w_TypeError, + "don't know how to handle %s in error callback", typename) + +def xmlcharrefreplace_errors(space, w_exc): + check_exception(space, w_exc) + if space.isinstance_w(w_exc, space.w_UnicodeEncodeError): + obj = space.realunicode_w(space.getattr(w_exc, space.wrap('object'))) + start = space.int_w(space.getattr(w_exc, space.wrap('start'))) + w_end = space.getattr(w_exc, space.wrap('end')) + end = space.int_w(w_end) + builder = UnicodeBuilder() + pos = start + while pos < end: + ch = obj[pos] + builder.append(u"&#") + builder.append(unicode(ord(ch))) + builder.append(u";") + pos += 1 + return space.newtuple([space.wrap(builder.build()), w_end]) + else: + typename = space.type(w_exc).getname(space, '?') + raise operationerrfmt(space.w_TypeError, + "don't know how to handle %s in error callback", typename) + +def backslashreplace_errors(space, w_exc): + check_exception(space, w_exc) + if space.isinstance_w(w_exc, space.w_UnicodeEncodeError): + obj = space.realunicode_w(space.getattr(w_exc, space.wrap('object'))) + start = space.int_w(space.getattr(w_exc, space.wrap('start'))) + w_end = space.getattr(w_exc, space.wrap('end')) + end = space.int_w(w_end) + builder = UnicodeBuilder() + pos = start + while pos < end: + oc = ord(obj[pos]) + num = hex(oc) + if (oc >= 0x10000): + builder.append(u"\\U") + zeros = 8 elif (oc >= 0x100): - p += 'u' - p += "%.4x" % ord(c) + builder.append(u"\\u") + zeros = 4 else: - p += 'x' - p += "%.2x" % ord(c) - return u''.join(p), exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) -""") + builder.append(u"\\x") + zeros = 2 + nb = zeros + 2 - len(num) # num starts with '0x' + if nb > 0: + builder.append_multiple_char(u'0', nb) + builder.append_slice(unicode(num), 2, 8) + pos += 1 + return space.newtuple([space.wrap(builder.build()), w_end]) + else: + typename = space.type(w_exc).getname(space, '?') + raise operationerrfmt(space.w_TypeError, + "don't know how to handle %s in error callback", typename) def register_builtin_error_handlers(space): + "NOT_RPYTHON" state = space.fromcache(CodecState) for error in ("strict", "ignore", "replace", "xmlcharrefreplace", "backslashreplace"): name = error + "_errors" - state.codec_error_registry[error] = app_errors.wget(space, name) + state.codec_error_registry[error] = space.wrap(interp2app(globals()[name])) def lookup_error(space, errors): @@ -312,6 +358,7 @@ "utf_16_encode", "utf_16_be_encode", "utf_16_le_encode", + "raw_unicode_escape_encode", ]: make_encoder_wrapper(encoders) @@ -322,6 +369,7 @@ "utf_16_decode", "utf_16_be_decode", "utf_16_le_decode", + "raw_unicode_escape_decode", ]: make_decoder_wrapper(decoders) Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Mon Jun 28 13:46:43 2010 @@ -15,7 +15,6 @@ def test_bigU_codecs(self): import sys - oldmaxunicode = sys.maxunicode if sys.maxunicode <= 0xffff: return # this test cannot run on UCS2 builds u = u'\U00010001\U00020002\U00030003\U00040004\U00050005' @@ -23,17 +22,14 @@ 'raw_unicode_escape', 'unicode_escape', 'unicode_internal'): assert unicode(u.encode(encoding),encoding) == u - sys.maxunicode = oldmaxunicode def test_ucs4(self): import sys - oldmaxunicode = sys.maxunicode if sys.maxunicode <= 0xffff: - sys.maxunicode = 0xffffffff + return # this test cannot run on UCS2 builds x = u'\U00100000' y = x.encode("raw-unicode-escape").decode("raw-unicode-escape") assert x == y - sys.maxunicode = oldmaxunicode def test_named_unicode(self): assert unicode('\\N{SPACE}','unicode-escape') == u" " Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Mon Jun 28 13:46:43 2010 @@ -491,6 +491,104 @@ res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 128) return res +# ____________________________________________________________ +# Raw unicode escape + +def str_decode_raw_unicode_escape(s, size, errors, final=False, + errorhandler=None): + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + if (size == 0): + return u'', 0 + + result = UnicodeBuilder(size) + pos = 0 + while pos < len(s): + ch = s[pos] + + # Non-escape characters are interpreted as Unicode ordinals + if (ch != '\\'): + result.append(unichr(ord(ch))) + pos += 1 + continue + + startinpos = pos + # \u-escapes are only interpreted iff the number of leading + # backslashes is odd + bs = pos + while pos < size: + pos += 1 + if (s[pos] != '\\'): + break + result.append(u'\\') + + # we have a backslash at the end of the string, stop here + if pos >= size: + result.append(u'\\') + break + + if (((pos - bs) & 1) == 0 or + pos >= size or + (s[pos] != 'u' and s[pos] != 'U')) : + result.append(u'\\') + result.append(unichr(ord(s[pos]))) + pos += 1 + continue + + if s[pos] == 'u': + count = 4 + else: + count = 8 + pos += 1 + + # \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 + x = 0 + try: + x = int(s[pos:pos+count], 16) + except ValueError: + res, pos = errorhandler(errors, "rawunicodeescape", + "truncated \\uXXXX", + s, pos, size) + result.append(res) + continue + + if (x > MAXUNICODE): + res, pos = errorhandler(errors, "rawunicodeescape", + "\\Uxxxxxxxx out of range", + s, pos, size) + result.append(res) + continue + + result.append(unichr(x)) + pos += count + + return result.build(), pos + +def unicode_encode_raw_unicode_escape(s, size, errors, errorhandler=None): + # errorhandler is not used: this function cannot cause Unicode errors + if (size == 0): + return '' + result = StringBuilder(size) + pos = 0 + while pos < size: + oc = ord(s[pos]) + if oc < 0x100: + result.append(chr(oc)) + else: + num = hex(oc) + if (oc >= 0x10000): + result.append("\\U") + zeros = 8 + else: + result.append("\\u") + zeros = 4 + nb = zeros + 2 - len(num) # num starts with '0x' + if nb > 0: + result.append_multiple_char('0', nb) + result.append_slice(num, 2, 8) + pos += 1 + + return result.build() # ____________________________________________________________ # MBCS codecs for Windows From benjamin at codespeak.net Mon Jun 28 16:30:49 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 16:30:49 +0200 (CEST) Subject: [pypy-svn] r75633 - pypy/branch/fast-forward/pypy/module/__builtin__ Message-ID: <20100628143049.96B4836C22E@codespeak.net> Author: benjamin Date: Mon Jun 28 16:30:47 2010 New Revision: 75633 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py Log: reword comment Modified: pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/descriptor.py Mon Jun 28 16:30:47 2010 @@ -195,8 +195,8 @@ setter = interp2app(W_Property.setter), deleter = interp2app(W_Property.deleter), ) -# This allows us to have a __doc__ of the property type and a __doc__ descriptor -# for the instances. +# This allows there to be a __doc__ of the property type and a __doc__ +# descriptor for the instances. W_Property.typedef.rawdict['__doc__'] = interp_attrproperty_w('w_doc', W_Property) From afa at codespeak.net Mon Jun 28 17:05:27 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 28 Jun 2010 17:05:27 +0200 (CEST) Subject: [pypy-svn] r75634 - in pypy/branch/interplevel-codecs/pypy: module/_codecs module/_codecs/test objspace/std rlib Message-ID: <20100628150527.2A1EF282BE3@codespeak.net> Author: afa Date: Mon Jun 28 17:05:25 2010 New Revision: 75634 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py pypy/branch/interplevel-codecs/pypy/objspace/std/unicodeobject.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: Rewrite the unicode-escape codec at interplevel. Use it for unicode.__repr__ Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Mon Jun 28 17:05:25 2010 @@ -9,8 +9,6 @@ 'charmap_encode' : 'app_codecs.charmap_encode', 'escape_decode' : 'app_codecs.escape_decode', 'escape_encode' : 'app_codecs.escape_encode', - 'unicode_escape_decode' : 'app_codecs.unicode_escape_decode', - 'unicode_escape_encode' : 'app_codecs.unicode_escape_encode', 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', 'unicode_internal_encode' : 'app_codecs.unicode_internal_encode', 'utf_7_decode' : 'app_codecs.utf_7_decode', @@ -42,6 +40,8 @@ 'charbuffer_encode': 'interp_codecs.buffer_encode', 'readbuffer_encode': 'interp_codecs.buffer_encode', 'charmap_decode' : 'interp_codecs.charmap_decode', + 'unicode_escape_decode' : 'interp_codecs.unicode_escape_decode', + 'unicode_escape_encode' : 'interp_codecs.unicode_escape_encode', 'raw_unicode_escape_decode' : 'interp_codecs.raw_unicode_escape_decode', 'raw_unicode_escape_encode' : 'interp_codecs.raw_unicode_escape_encode', } Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Mon Jun 28 17:05:25 2010 @@ -53,21 +53,6 @@ res = u''.join(res) return res, len(data) -def unicode_escape_encode( obj, errors='strict'): - """None - """ - res = unicodeescape_string(obj, len(obj), 0) - res = ''.join(res) - return res, len(obj) - -def unicode_escape_decode( data, errors='strict'): - """None - """ - res = PyUnicode_DecodeUnicodeEscape(data, len(data), errors) - res = u''.join(res) - return res, len(data) - - def charmap_encode(obj, errors='strict', mapping=None): """None """ @@ -422,84 +407,6 @@ unicode_empty = u'' -def unicodeescape_string(s, size, quotes): - - p = [] - if (quotes) : - p += 'u' - if (s.find('\'') != -1 and s.find('"') == -1): - p += '"' - else: - p += '\'' - pos = 0 - while (pos < size): - ch = s[pos] - #/* Escape quotes */ - if (quotes and (ch == p[1] or ch == '\\')): - p += '\\' - p += chr(ord(ch)) - pos += 1 - continue - -#ifdef Py_UNICODE_WIDE - #/* Map 21-bit characters to '\U00xxxxxx' */ - elif (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x' % ord(ch) - pos += 1 - continue -#endif - #/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ - elif (ord(ch) >= 0xD800 and ord(ch) < 0xDC00): - pos += 1 - ch2 = s[pos] - - if (ord(ch2) >= 0xDC00 and ord(ch2) <= 0xDFFF): - ucs = (((ord(ch) & 0x03FF) << 10) | (ord(ch2) & 0x03FF)) + 0x00010000 - p += '\\' - p += 'U' - p += '%08x' % ucs - pos += 1 - continue - - #/* Fall through: isolated surrogates are copied as-is */ - pos -= 1 - - #/* Map 16-bit characters to '\uxxxx' */ - elif (ord(ch) >= 256): - p += '\\' - p += 'u' - p += '%04x' % ord(ch) - - #/* Map special whitespace to '\t', \n', '\r' */ - elif (ch == '\t'): - p += '\\' - p += 't' - - elif (ch == '\n'): - p += '\\' - p += 'n' - - elif (ch == '\r'): - p += '\\' - p += 'r' - elif ch == '\\': - p += '\\\\' - - #/* Map non-printable US ASCII to '\xhh' */ - elif (ch < ' ' or ord(ch) >= 0x7F) : - p += '\\' - p += 'x' - p += '%02x' % ord(ch) - #/* Copy everything else as-is */ - else: - p += chr(ord(ch)) - pos += 1 - if (quotes): - p += p[1] - return p - def unicode_call_errorhandler(errors, encoding, reason, input, startinpos, endinpos, decode=True): @@ -522,160 +429,6 @@ -hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10, 16)] - -def hexescape(s, pos, digits, message, errors): - import sys - chr = 0 - p = [] - if (pos+digits>len(s)): - message = "end of string in escape sequence" - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-2, len(s)) - p += x[0] - pos = x[1] - else: - try: - chr = int(s[pos:pos+digits], 16) - except ValueError: - endinpos = pos - while s[endinpos] in hexdigits: - endinpos += 1 - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-2, - endinpos+1) - p += x[0] - pos = x[1] - #/* when we get here, chr is a 32-bit unicode character */ - else: - if chr <= sys.maxunicode: - p += unichr(chr) - pos += digits - - elif (chr <= 0x10ffff): - chr -= 0x10000L - p += unichr(0xD800 + (chr >> 10)) - p += unichr(0xDC00 + (chr & 0x03FF)) - pos += digits - else: - message = "illegal Unicode character" - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-2, - pos+1) - p += x[0] - pos = x[1] - res = p - return res, pos - -def PyUnicode_DecodeUnicodeEscape(s, size, errors): - import sys - - if (size == 0): - return u'' - - p = [] - pos = 0 - while (pos < size): -## /* Non-escape characters are interpreted as Unicode ordinals */ - if (s[pos] != '\\') : - p += unichr(ord(s[pos])) - pos += 1 - continue -## /* \ - Escapes */ - else: - pos += 1 - if pos >= len(s): - errmessage = "\\ at end of string" - unicode_call_errorhandler(errors, "unicodeescape", errmessage, s, pos-1, size) - ch = s[pos] - pos += 1 - ## /* \x escapes */ - if ch == '\n': pass - elif ch == '\\' : p += u'\\' - elif ch == '\'': p += u'\'' - elif ch == '\"': p += u'\"' - elif ch == 'b' : p += u'\b' - elif ch == 'f' : p += u'\014' #/* FF */ - elif ch == 't' : p += u'\t' - elif ch == 'n' : p += u'\n' - elif ch == 'r' : p += u'\r' - elif ch == 'v': p += u'\013' #break; /* VT */ - elif ch == 'a': p += u'\007' # break; /* BEL, not classic C */ - elif '0' <= ch <= '7': - x = ord(ch) - ord('0') - if pos < size: - ch = s[pos] - if '0' <= ch <= '7': - pos += 1 - x = (x<<3) + ord(ch) - ord('0') - if pos < size: - ch = s[pos] - if '0' <= ch <= '7': - pos += 1 - x = (x<<3) + ord(ch) - ord('0') - p += unichr(x) - ## /* hex escapes */ - ## /* \xXX */ - elif ch == 'x': - digits = 2 - message = "truncated \\xXX escape" - x = hexescape(s, pos, digits, message, errors) - p += x[0] - pos = x[1] - - # /* \uXXXX */ - elif ch == 'u': - digits = 4 - message = "truncated \\uXXXX escape" - x = hexescape(s, pos, digits, message, errors) - p += x[0] - pos = x[1] - - # /* \UXXXXXXXX */ - elif ch == 'U': - digits = 8 - message = "truncated \\UXXXXXXXX escape" - x = hexescape(s, pos, digits, message, errors) - p += x[0] - pos = x[1] -## /* \N{name} */ - elif ch == 'N': - message = "malformed \\N character escape" - #pos += 1 - look = pos - try: - import unicodedata - except ImportError: - message = "\\N escapes not supported (can't load unicodedata module)" - unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, size) - if look < size and s[look] == '{': - #/* look for the closing brace */ - while (look < size and s[look] != '}'): - look += 1 - if (look > pos+1 and look < size and s[look] == '}'): - #/* found a name. look it up in the unicode database */ - message = "unknown Unicode character name" - st = s[pos+1:look] - try: - ch = unicodedata._get_code("%s" % st) - except KeyError, e: - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, look+1) - p += x[0] - pos = x[1] - else: - pos = look + 1 - if ch <= sys.maxunicode: - p += unichr(ch) - else: - ch -= 0x10000L - p += unichr(0xD800 + (ch >> 10)) - p += unichr(0xDC00 + (ch & 0x03FF)) - else: - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, look+1) - else: - x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, look+1) - else: - p += '\\' - p += ch - return p - def charmapencode_output(c, mapping): rep = mapping[c] Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Mon Jun 28 17:05:25 2010 @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped, interp2app +from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.baseobjspace import W_Root from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy.rlib.objectmodel import we_are_translated @@ -13,6 +14,8 @@ self.decode_error_handler = self.make_errorhandler(space, True) self.encode_error_handler = self.make_errorhandler(space, False) + self.unicodedata_getcode = None + def make_errorhandler(self, space, decode): def unicode_call_errorhandler(errors, encoding, reason, input, startpos, endpos): @@ -53,6 +56,17 @@ return replace, newpos return unicode_call_errorhandler + def get_unicodedata_function(self, space): + if self.unicodedata_getcode: + return self.unicodedata_getcode + w_builtin = space.getbuiltinmodule('__builtin__') + w_import = space.getattr(w_builtin, space.wrap("__import__")) + w_unicodedata = space.call_function(w_import, + space.wrap("unicodedata")) + self.unicodedata_getcode = space.getattr(w_unicodedata, + space.wrap("_get_code")) + return self.unicodedata_getcode + def _freeze_(self): assert not self.codec_search_path return False @@ -184,7 +198,7 @@ while pos < end: ch = obj[pos] builder.append(u"&#") - builder.append(unicode(ord(ch))) + builder.append(unicode(str(ord(ch)))) builder.append(u";") pos += 1 return space.newtuple([space.wrap(builder.build()), w_end]) @@ -358,6 +372,7 @@ "utf_16_encode", "utf_16_be_encode", "utf_16_le_encode", + "unicode_escape_encode", "raw_unicode_escape_encode", ]: make_encoder_wrapper(encoders) @@ -471,3 +486,40 @@ res = builder.build() return space.newtuple([space.wrap(res), space.wrap(size)]) charmap_decode.unwrap_spec = [ObjSpace, str, str, W_Root] + +# ____________________________________________________________ +# Unicode escape + +class UnicodeData_Handler: + def __init__(self, space): + self.space = space + state = space.fromcache(CodecState) + self.get_code = state.get_unicodedata_function(space) + + def call(self, name): + space = self.space + try: + w_code = space.call_function(self.get_code, space.wrap(name)) + except OperationError, e: + if not e.match(space, space.w_KeyError): + raise + return -1 + return space.int_w(w_code) + + at unwrap_spec(ObjSpace, 'bufferstr', str, W_Root) +def unicode_escape_decode(space, string, errors="strict", w_final=False): + final = space.is_true(w_final) + state = space.fromcache(CodecState) + errorhandler=state.decode_error_handler + + try: + unicode_name_handler = UnicodeData_Handler(space) + except OperationError: + unicode_name_handler = None + + result, consumed = runicode.str_decode_unicode_escape( + string, len(string), errors, + final, state.decode_error_handler, + unicode_name_handler) + + return space.newtuple([space.wrap(result), space.wrap(consumed)]) Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Mon Jun 28 17:05:25 2010 @@ -1,7 +1,6 @@ import autopath from pypy.conftest import gettestobjspace -from pypy.module._codecs.app_codecs import unicode_escape_encode,\ - charmap_encode, unicode_escape_decode +from pypy.module._codecs.app_codecs import charmap_encode class AppTestCodecs: @@ -120,6 +119,11 @@ map = tuple([unichr(i) for i in range(256)]) assert charmap_decode('xxx\xff', 'strict', map) == (u'xxx\xff', 4) + def test_unicode_escape(self): + from _codecs import unicode_escape_encode, unicode_escape_decode + assert unicode_escape_encode(u'abc') == (u'abc'.encode('unicode_escape'), 3) + assert unicode_escape_decode('abc') == (u'abc'.decode('unicode_escape'), 3) + assert unicode_escape_decode('\\x61\\x62\\x63') == (u'abc', 12) class AppTestPartialEvaluation: @@ -542,6 +546,7 @@ def test_unicode_escape(self): assert u'\\'.encode('unicode-escape') == '\\\\' assert '\\\\'.decode('unicode-escape') == u'\\' + assert u'\ud801'.encode('unicode-escape') == '\\ud801' def test_mbcs(self): import sys @@ -557,8 +562,3 @@ def test_charmap_encode(self): assert charmap_encode(u'xxx') == ('xxx', 3) assert charmap_encode(u'xxx', 'strict', {ord('x'): 'XX'}) == ('XXXXXX', 6) - - def test_unicode_escape(self): - assert unicode_escape_encode(u'abc') == (u'abc'.encode('unicode_escape'), 3) - assert unicode_escape_decode('abc') == (u'abc'.decode('unicode_escape'), 3) - assert unicode_escape_decode('\\x61\\x62\\x63') == (u'abc', 12) Modified: pypy/branch/interplevel-codecs/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/interplevel-codecs/pypy/objspace/std/unicodeobject.py Mon Jun 28 17:05:25 2010 @@ -12,6 +12,7 @@ from pypy.rlib.rarithmetic import intmask, ovfcheck from pypy.rlib.objectmodel import compute_hash from pypy.rlib.rstring import string_repeat +from pypy.rlib.runicode import unicode_encode_unicode_escape from pypy.module.unicodedata import unicodedb_4_1_0 as unicodedb from pypy.tool.sourcetools import func_with_new_name @@ -892,101 +893,11 @@ space.wrap("character mapping must return integer, None or unicode")) return W_UnicodeObject(u''.join(result)) -# Move this into the _codecs module as 'unicodeescape_string (Remember to cater for quotes)' def repr__Unicode(space, w_unicode): - hexdigits = "0123456789abcdef" chars = w_unicode._value size = len(chars) - - singlequote = doublequote = False - for c in chars: - if c == u'\'': - singlequote = True - elif c == u'"': - doublequote = True - if singlequote and not doublequote: - quote = '"' - else: - quote = '\'' - result = ['u', quote] - j = 0 - while j= 0x10000: - # Resize if needed - result.extend(['\\', "U", - hexdigits[(code >> 28) & 0xf], - hexdigits[(code >> 24) & 0xf], - hexdigits[(code >> 20) & 0xf], - hexdigits[(code >> 16) & 0xf], - hexdigits[(code >> 12) & 0xf], - hexdigits[(code >> 8) & 0xf], - hexdigits[(code >> 4) & 0xf], - hexdigits[(code >> 0) & 0xf], - ]) - j += 1 - continue - if code >= 0xD800 and code < 0xDC00: - if j < size - 1: - ch2 = chars[j+1] - code2 = ord(ch2) - if code2 >= 0xDC00 and code2 <= 0xDFFF: - code = (((code & 0x03FF) << 10) | (code2 & 0x03FF)) + 0x00010000 - result.extend(['\\', "U", - hexdigits[(code >> 28) & 0xf], - hexdigits[(code >> 24) & 0xf], - hexdigits[(code >> 20) & 0xf], - hexdigits[(code >> 16) & 0xf], - hexdigits[(code >> 12) & 0xf], - hexdigits[(code >> 8) & 0xf], - hexdigits[(code >> 4) & 0xf], - hexdigits[(code >> 0) & 0xf], - ]) - j += 2 - continue - - if code >= 0x100: - result.extend(['\\', "u", - hexdigits[(code >> 12) & 0xf], - hexdigits[(code >> 8) & 0xf], - hexdigits[(code >> 4) & 0xf], - hexdigits[(code >> 0) & 0xf], - ]) - j += 1 - continue - if code == ord('\\') or code == ord(quote): - result.append('\\') - result.append(chr(code)) - j += 1 - continue - if code == ord('\t'): - result.append('\\') - result.append('t') - j += 1 - continue - if code == ord('\r'): - result.append('\\') - result.append('r') - j += 1 - continue - if code == ord('\n'): - result.append('\\') - result.append('n') - j += 1 - continue - if code < ord(' ') or code >= 0x7f: - result.extend(['\\', "x", - hexdigits[(code >> 4) & 0xf], - hexdigits[(code >> 0) & 0xf], - ]) - j += 1 - continue - result.append(chr(code)) - j += 1 - result.append(quote) - return space.wrap(''.join(result)) - + s = unicode_encode_unicode_escape(chars, size, "strict", quotes=True) + return space.wrap(s) def mod__Unicode_ANY(space, w_format, w_values): return mod_format(space, w_format, w_values, do_unicode=True) Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Mon Jun 28 17:05:25 2010 @@ -319,7 +319,7 @@ result = UnicodeBuilder(size // 2) #XXX I think the errors are not correctly handled here - while (pos < len(s)): + while pos < size: # remaining bytes at the end? (size should be even) if len(s) - pos < 2: if not final: @@ -425,7 +425,7 @@ # latin1 is equivalent to the first 256 ordinals in Unicode. pos = 0 result = UnicodeBuilder(size) - while (pos < size): + while pos < size: result.append(unichr(ord(s[pos]))) pos += 1 return result.build(), pos @@ -438,7 +438,7 @@ # ASCII is equivalent to the first 128 ordinals in Unicode. result = UnicodeBuilder(size) pos = 0 - while pos < len(s): + while pos < size: c = s[pos] if ord(c) < 128: result.append(unichr(ord(c))) @@ -465,7 +465,7 @@ return '' result = StringBuilder(size) pos = 0 - while pos < len(p): + while pos < size: ch = p[pos] if ord(ch) < limit: @@ -492,6 +492,248 @@ return res # ____________________________________________________________ +# Unicode escape + +hexdigits = "0123456789ABCDEFabcdef" + +def hexescape(builder, s, pos, digits, errorhandler, message, errors): + import sys + chr = 0 + if (pos+digits>len(s)): + message = "end of string in escape sequence" + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-2, len(s)) + builder.append(res) + else: + try: + chr = int(s[pos:pos+digits], 16) + except ValueError: + endinpos = pos + while s[endinpos] in hexdigits: + endinpos += 1 + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-2, endinpos+1) + builder.append(res) + else: + # when we get here, chr is a 32-bit unicode character + if chr <= MAXUNICODE: + builder.append(unichr(chr)) + pos += digits + + elif (chr <= 0x10ffff): + chr -= 0x10000L + builder.append(unichr(0xD800 + (chr >> 10))) + builder.append(unichr(0xDC00 + (chr & 0x03FF))) + pos += digits + else: + message = "illegal Unicode character" + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-2, pos+1) + builder.append(res) + return pos + +def str_decode_unicode_escape(s, size, errors, final=False, + errorhandler=False, + unicodedata_handler=None): + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + + if (size == 0): + return u'', 0 + + builder = UnicodeBuilder(size) + pos = 0 + while pos < size: + ch = s[pos] + + # Non-escape characters are interpreted as Unicode ordinals + if (ch != '\\') : + builder.append(unichr(ord(ch))) + pos += 1 + continue + + # - Escapes + pos += 1 + if pos >= size: + message = "\\ at end of string" + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-1, size) + builder.append(res) + continue + + ch = s[pos] + pos += 1 + # \x escapes */ + if ch == '\n': pass + elif ch == '\\': builder.append(u'\\') + elif ch == '\'': builder.append(u'\'') + elif ch == '\"': builder.append(u'\"') + elif ch == 'b' : builder.append(u'\b') + elif ch == 'f' : builder.append(u'\f') + elif ch == 't' : builder.append(u'\t') + elif ch == 'n' : builder.append(u'\n') + elif ch == 'r' : builder.append(u'\r') + elif ch == 'v' : builder.append(u'\v') + elif ch == 'a' : builder.append(u'\a') + elif '0' <= ch <= '7': + x = ord(ch) - ord('0') + if pos < size: + ch = s[pos] + if '0' <= ch <= '7': + pos += 1 + x = (x<<3) + ord(ch) - ord('0') + if pos < size: + ch = s[pos] + if '0' <= ch <= '7': + pos += 1 + x = (x<<3) + ord(ch) - ord('0') + builder.append(unichr(x)) + # hex escapes + # \xXX + elif ch == 'x': + digits = 2 + message = "truncated \\xXX escape" + pos = hexescape(builder, s, pos, digits, + errorhandler, message, errors) + + # \uXXXX + elif ch == 'u': + digits = 4 + message = "truncated \\uXXXX escape" + pos = hexescape(builder, s, pos, digits, + errorhandler, message, errors) + + # \UXXXXXXXX + elif ch == 'U': + digits = 8 + message = "truncated \\UXXXXXXXX escape" + pos = hexescape(builder, s, pos, digits, + errorhandler, message, errors) + + # \N{name} + elif ch == 'N': + message = "malformed \\N character escape" + #pos += 1 + look = pos + if unicodedata_handler is None: + message = ("\\N escapes not supported " + "(can't load unicodedata module)") + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-1, size) + builder.append(res) + continue + + if look < size and s[look] == '{': + # look for the closing brace + while (look < size and s[look] != '}'): + look += 1 + if (look > pos+1 and look < size and s[look] == '}'): + # found a name. look it up in the unicode database + message = "unknown Unicode character name" + name = s[pos+1:look] + code = unicodedata_handler.call(name) + if code < 0: + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-1, look+1) + builder.append(res) + continue + pos = look + 1 + if code <= MAXUNICODE: + builder.append(unichr(code)) + else: + code -= 0x10000L + builder.append(unichr(0xD800 + (code >> 10))) + builder.append(unichr(0xDC00 + (code & 0x03FF))) + else: + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-1, look+1) + builder.append(res) + else: + res, pos = errorhandler(errors, "unicodeescape", + message, s, pos-1, look+1) + builder.append(res) + else: + builder.append(u'\\') + builder.append(unichr(ord(ch))) + + return builder.build(), pos + +def unicode_encode_unicode_escape(s, size, errors, errorhandler=None, quotes=False): + # errorhandler is not used: this function cannot cause Unicode errors + result = StringBuilder(size) + + if quotes: + if s.find(u'\'') != -1 and s.find(u'\"') == -1: + quote = ord('\"') + result.append('u"') + else: + quote = ord('\'') + result.append('u\'') + else: + quote = 0 + + if size == 0: + return '' + + pos = 0 + while pos < size: + ch = s[pos] + oc = ord(ch) + + # Escape quotes + if quotes and (oc == quote or ch == '\\'): + result.append('\\') + result.append(chr(oc)) + pos += 1 + continue + + if oc > 0x10000: + raw_unicode_escape_helper(result, oc) + pos += 1 + continue + + if 0xD800 <= oc < 0xDC00 and pos + 1 < size: + # Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes + pos += 1 + oc2 = ord(s[pos]) + + if 0xDC00 <= oc2 < 0xDFFF: + ucs = (((oc & 0x03FF) << 10) | (oc2 & 0x03FF)) + 0x00010000 + raw_unicode_escape_helper(result, ucs) + pos += 1 + continue + # Fall through: isolated surrogates are copied as-is + pos -= 1 + + # Map 16-bit characters to '\uxxxx' + if oc >= 0x100: + raw_unicode_escape_helper(result, oc) + pos += 1 + continue + + # Map special whitespace to '\t', \n', '\r' + if ch == '\t': + result.append('\\t') + elif ch == '\n': + result.append('\\n') + elif ch == '\r': + result.append('\\r') + elif ch == '\\': + result.append('\\\\') + + # Map non-printable US ASCII to '\xhh' + elif (oc < 32 or oc >= 0x7F) : + raw_unicode_escape_helper(result, oc) + # Copy everything else as-is + else: + result.append(chr(oc)) + pos += 1 + + if quotes: + result.append(chr(quote)) + return result.build() + +# ____________________________________________________________ # Raw unicode escape def str_decode_raw_unicode_escape(s, size, errors, final=False, @@ -503,7 +745,7 @@ result = UnicodeBuilder(size) pos = 0 - while pos < len(s): + while pos < size: ch = s[pos] # Non-escape characters are interpreted as Unicode ordinals @@ -518,7 +760,7 @@ bs = pos while pos < size: pos += 1 - if (s[pos] != '\\'): + if pos == size or s[pos] != '\\': break result.append(u'\\') @@ -564,6 +806,19 @@ return result.build(), pos +def raw_unicode_escape_helper(result, char): + num = hex(char) + if char >= 0x10000: + result.append("\\U") + zeros = 8 + else: + result.append("\\u") + zeros = 4 + nb = zeros + 2 - len(num) # num starts with '0x' + if nb > 0: + result.append_multiple_char('0', nb) + result.append_slice(num, 2, 8) + def unicode_encode_raw_unicode_escape(s, size, errors, errorhandler=None): # errorhandler is not used: this function cannot cause Unicode errors if (size == 0): @@ -575,17 +830,7 @@ if oc < 0x100: result.append(chr(oc)) else: - num = hex(oc) - if (oc >= 0x10000): - result.append("\\U") - zeros = 8 - else: - result.append("\\u") - zeros = 4 - nb = zeros + 2 - len(num) # num starts with '0x' - if nb > 0: - result.append_multiple_char('0', nb) - result.append_slice(num, 2, 8) + raw_unicode_escape_helper(result, oc) pos += 1 return result.build() From benjamin at codespeak.net Mon Jun 28 17:22:02 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 17:22:02 +0200 (CEST) Subject: [pypy-svn] r75635 - in pypy/branch/fast-forward/pypy/module/exceptions: . test Message-ID: <20100628152202.0C1D7282B9D@codespeak.net> Author: benjamin Date: Mon Jun 28 17:22:00 2010 New Revision: 75635 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Log: allow BaseException.message to be deleted Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 17:22:00 2010 @@ -158,6 +158,30 @@ space.call_method(w_olddict, 'update', w_dict) descr_setstate.unwrap_spec = ['self', ObjSpace, W_Root] + def descr_message_get(space, self): + w_dict = self.w_dict + if w_dict is not None: + w_msg = space.finditem(w_dict, space.wrap("message")) + if w_msg is not None: + return w_msg + if self.w_message is None: + raise OperationError(space.w_AttributeError, + space.wrap("message was deleted")) + return self.w_message + + def descr_message_set(space, self, w_new): + space.setitem(self.getdict(), space.wrap("message"), w_new) + + def descr_message_del(space, self): + w_dict = self.w_dict + if w_dict is not None: + try: + space.delitem(w_dict, space.wrap("message")) + except OperationError, e: + if not e.match(space.w_KeyError): + raise + self.w_message = None + def _new(cls, basecls=None): if basecls is None: basecls = cls @@ -182,7 +206,9 @@ __getitem__ = interp2app(W_BaseException.descr_getitem), __reduce__ = interp2app(W_BaseException.descr_reduce), __setstate__ = interp2app(W_BaseException.descr_setstate), - message = readwrite_attrproperty_w('w_message', W_BaseException), + message = GetSetProperty(W_BaseException.descr_message_get, + W_BaseException.descr_message_set, + W_BaseException.descr_message_del), args = GetSetProperty(W_BaseException.descr_getargs, W_BaseException.descr_setargs), ) Modified: pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Mon Jun 28 17:22:00 2010 @@ -31,6 +31,8 @@ assert x[1:2] == (2,) x.message = "xyz" assert x.message == "xyz" + del x.message + assert not hasattr(x, "message") def test_kwargs(self): from exceptions import Exception From benjamin at codespeak.net Mon Jun 28 17:46:39 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 17:46:39 +0200 (CEST) Subject: [pypy-svn] r75636 - pypy/branch/fast-forward/pypy/module/exceptions Message-ID: <20100628154639.181A0282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 17:46:38 2010 New Revision: 75636 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Log: deprecate BaseException.message Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 17:46:38 2010 @@ -167,6 +167,8 @@ if self.w_message is None: raise OperationError(space.w_AttributeError, space.wrap("message was deleted")) + space.warn("BaseException.message has been deprecated as of Python 2.6", + space.w_DeprecationWarning) return self.w_message def descr_message_set(space, self, w_new): From benjamin at codespeak.net Mon Jun 28 17:47:45 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 17:47:45 +0200 (CEST) Subject: [pypy-svn] r75637 - pypy/branch/fast-forward/pypy/module/imp Message-ID: <20100628154745.AD3CD282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 17:47:44 2010 New Revision: 75637 Modified: pypy/branch/fast-forward/pypy/module/imp/__init__.py Log: move reload to the imp module Modified: pypy/branch/fast-forward/pypy/module/imp/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/imp/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/imp/__init__.py Mon Jun 28 17:47:44 2010 @@ -25,6 +25,7 @@ 'init_frozen': 'interp_imp.init_frozen', 'is_builtin': 'interp_imp.is_builtin', 'is_frozen': 'interp_imp.is_frozen', + 'reload': 'interp_imp.reload', 'lock_held': 'interp_imp.lock_held', 'acquire_lock': 'interp_imp.acquire_lock', From benjamin at codespeak.net Mon Jun 28 17:49:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 17:49:09 +0200 (CEST) Subject: [pypy-svn] r75638 - pypy/branch/fast-forward/pypy/module/imp Message-ID: <20100628154909.6E8F7282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 17:49:08 2010 New Revision: 75638 Modified: pypy/branch/fast-forward/pypy/module/imp/__init__.py Log: typo Modified: pypy/branch/fast-forward/pypy/module/imp/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/imp/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/imp/__init__.py Mon Jun 28 17:49:08 2010 @@ -25,7 +25,7 @@ 'init_frozen': 'interp_imp.init_frozen', 'is_builtin': 'interp_imp.is_builtin', 'is_frozen': 'interp_imp.is_frozen', - 'reload': 'interp_imp.reload', + 'reload': 'importing.reload', 'lock_held': 'interp_imp.lock_held', 'acquire_lock': 'interp_imp.acquire_lock', From benjamin at codespeak.net Mon Jun 28 18:15:10 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 18:15:10 +0200 (CEST) Subject: [pypy-svn] r75639 - in pypy/branch/fast-forward/pypy/module/exceptions: . test Message-ID: <20100628161510.4CD41282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 18:15:08 2010 New Revision: 75639 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Log: add workaround for unicode message Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 18:15:08 2010 @@ -117,6 +117,22 @@ return space.str(space.newtuple(self.args_w)) descr_str.unwrap_spec = ['self', ObjSpace] + def descr_unicode(self, space): + w_str = space.lookup(self, "__str__") + w_base_str = space.wrap(W_BaseException.typedef.rawdict["__str__"]) + if not space.is_w(w_str, w_base_str): + w_as_str = space.get_and_call_function(w_str, space.wrap(self)) + return space.call_function(space.w_unicode, w_as_str) + lgt = len(self.args_w) + if lgt == 0: + return space.wrap(u"") + if lgt == 1: + return space.call_function(space.w_unicode, self.args_w[0]) + else: + w_tup = space.newtuple(self.args_w) + return space.call_function(space.w_unicode, w_tup) + descr_unicode.unwrap_spec = ['self', ObjSpace] + def descr_repr(self, space): if self.args_w: args_repr = space.str_w(space.repr(space.newtuple(self.args_w))) @@ -202,6 +218,7 @@ __new__ = _new(W_BaseException), __init__ = interp2app(W_BaseException.descr_init), __str__ = interp2app(W_BaseException.descr_str), + __unicode__ = interp2app(W_BaseException.descr_unicode), __repr__ = interp2app(W_BaseException.descr_repr), __dict__ = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict, cls=W_BaseException), Modified: pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Mon Jun 28 18:15:08 2010 @@ -34,6 +34,14 @@ del x.message assert not hasattr(x, "message") + def test_unicode_message(self): + assert unicode(Exception(u"\xe1")) == u"\xe1" + class E(BaseException): + def __str__(self): + return u"\xe1" + e = E() + assert unicode(e) == u"\xe1" + def test_kwargs(self): from exceptions import Exception class X(Exception): From benjamin at codespeak.net Mon Jun 28 18:17:21 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 18:17:21 +0200 (CEST) Subject: [pypy-svn] r75640 - pypy/branch/fast-forward/pypy/module/exceptions Message-ID: <20100628161721.5D3FB282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 18:17:19 2010 New Revision: 75640 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Log: use consistent quoting Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 18:17:19 2010 @@ -727,14 +727,14 @@ if self.end == self.start + 1: badchar = ord(self.object[self.start]) if badchar <= 0xff: - return "%r codec can't encode character u'\\x%02x' in position %d: %s"%( + return "'%s' codec can't encode character u'\\x%02x' in position %d: %s"%( self.encoding, badchar, self.start, self.reason) if badchar <= 0xffff: - return "%r codec can't encode character u'\\u%04x' in position %d: %s"%( + return "'%s' codec can't encode character u'\\u%04x' in position %d: %s"%( self.encoding, badchar, self.start, self.reason) - return "%r codec can't encode character u'\\U%08x' in position %d: %s"%( + return "'%s' codec can't encode character u'\\U%08x' in position %d: %s"%( self.encoding, badchar, self.start, self.reason) - return "%r codec can't encode characters in position %d-%d: %s" % ( + return "'%s' codec can't encode characters in position %d-%d: %s" % ( self.encoding, self.start, self.end - 1, self.reason) """) descr_str.unwrap_spec = ['self', ObjSpace] From benjamin at codespeak.net Mon Jun 28 18:28:14 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 18:28:14 +0200 (CEST) Subject: [pypy-svn] r75641 - pypy/branch/fast-forward/pypy/module/exceptions Message-ID: <20100628162814.04A20282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 18:28:13 2010 New Revision: 75641 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Log: fix quoting again Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 18:28:13 2010 @@ -633,10 +633,10 @@ def descr_str(self, space): return space.appexec([self], """(self): if self.end == self.start + 1: - return "%r codec can't decode byte 0x%02x in position %d: %s"%( + return "'%s' codec can't decode byte 0x%02x in position %d: %s"%( self.encoding, ord(self.object[self.start]), self.start, self.reason) - return "%r codec can't decode bytes in position %d-%d: %s" % ( + return "'%s' codec can't decode bytes in position %d-%d: %s" % ( self.encoding, self.start, self.end - 1, self.reason) """) descr_str.unwrap_spec = ['self', ObjSpace] From benjamin at codespeak.net Mon Jun 28 18:38:01 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 18:38:01 +0200 (CEST) Subject: [pypy-svn] r75642 - in pypy/branch/fast-forward/pypy/module/exceptions: . test Message-ID: <20100628163801.805F0282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 18:37:59 2010 New Revision: 75642 Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Log: SyntaxError.msg is None by default Modified: pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/interp_exceptions.py Mon Jun 28 18:37:59 2010 @@ -499,7 +499,7 @@ self.w_lineno = space.w_None self.w_offset = space.w_None self.w_text = space.w_None - self.w_msg = space.wrap('') + self.w_msg = space.w_None self.w_print_file_and_line = space.w_None # what's that? W_BaseException.__init__(self, space) Modified: pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py (original) +++ pypy/branch/fast-forward/pypy/module/exceptions/test/test_exc.py Mon Jun 28 18:37:59 2010 @@ -131,6 +131,8 @@ def test_syntax_error(self): from exceptions import SyntaxError + s = SyntaxError() + assert s.msg is None s = SyntaxError(3) assert str(s) == '3' assert str(SyntaxError("a", "b", 123)) == "a" From benjamin at codespeak.net Mon Jun 28 18:50:14 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 18:50:14 +0200 (CEST) Subject: [pypy-svn] r75643 - pypy/branch/fast-forward/lib-python Message-ID: <20100628165014.B5C00282B90@codespeak.net> Author: benjamin Date: Mon Jun 28 18:50:13 2010 New Revision: 75643 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: add use modules to errno Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Mon Jun 28 18:50:13 2010 @@ -236,7 +236,7 @@ RegrTest('test_enumerate.py', core=True), RegrTest('test_eof.py', core=True), RegrTest('test_epoll.py'), - RegrTest('test_errno.py'), + RegrTest('test_errno.py', usemodules="errno"), RegrTest('test_exceptions.py', core=True), RegrTest('test_extcall.py', core=True), RegrTest('test_fcntl.py', usemodules='fcntl', skip=skip_win32), From afa at codespeak.net Mon Jun 28 18:53:43 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 28 Jun 2010 18:53:43 +0200 (CEST) Subject: [pypy-svn] r75644 - in pypy/branch/interplevel-codecs/pypy: module/_codecs rlib Message-ID: <20100628165343.EBD16282B90@codespeak.net> Author: afa Date: Mon Jun 28 18:53:42 2010 New Revision: 75644 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: Rewrite utf-7 codec at interp-level. This should dramatically reduce the generated C code. Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Mon Jun 28 18:53:42 2010 @@ -11,8 +11,6 @@ 'escape_encode' : 'app_codecs.escape_encode', 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', 'unicode_internal_encode' : 'app_codecs.unicode_internal_encode', - 'utf_7_decode' : 'app_codecs.utf_7_decode', - 'utf_7_encode' : 'app_codecs.utf_7_encode', 'charmap_build' : 'app_codecs.charmap_build' } interpleveldefs = { @@ -28,6 +26,8 @@ 'ascii_encode' : 'interp_codecs.ascii_encode', 'latin_1_decode' : 'interp_codecs.latin_1_decode', 'latin_1_encode' : 'interp_codecs.latin_1_encode', + 'utf_7_decode' : 'interp_codecs.utf_7_decode', + 'utf_7_encode' : 'interp_codecs.utf_7_encode', 'utf_8_decode' : 'interp_codecs.utf_8_decode', 'utf_8_encode' : 'interp_codecs.utf_8_encode', 'utf_16_be_decode' : 'interp_codecs.utf_16_be_decode', Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Mon Jun 28 18:53:42 2010 @@ -46,13 +46,6 @@ v = s[1:-1] return v, len(v) -def utf_7_decode( data, errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF7(data, len(data), errors) - res = u''.join(res) - return res, len(data) - def charmap_encode(obj, errors='strict', mapping=None): """None """ @@ -175,238 +168,8 @@ res = ''.join(res) return res, len(data) - -def utf_7_encode( obj, errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF7(obj, len(obj), 0, 0, errors) - res = ''.join(res) - return res, len(res) - # ---------------------------------------------------------------------- -##import sys -##""" Python implementation of CPythons builtin unicode codecs. -## -## Generally the functions in this module take a list of characters an returns -## a list of characters. -## -## For use in the PyPy project""" - - -## indicate whether a UTF-7 character is special i.e. cannot be directly -## encoded: -## 0 - not special -## 1 - special -## 2 - whitespace (optional) -## 3 - RFC2152 Set O (optional) - -utf7_special = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, -] - - -def SPECIAL(c, encodeO, encodeWS): - c = ord(c) - return (c>127 or utf7_special[c] == 1) or \ - (encodeWS and (utf7_special[(c)] == 2)) or \ - (encodeO and (utf7_special[(c)] == 3)) -def B64(n): - return ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) -def B64CHAR(c): - return (c.isalnum() or (c) == '+' or (c) == '/') -def UB64(c): - if (c) == '+' : - return 62 - elif (c) == '/': - return 63 - elif (c) >= 'a': - return ord(c) - 71 - elif (c) >= 'A': - return ord(c) - 65 - else: - return ord(c) + 4 - -def ENCODE( ch, bits) : - out = [] - while (bits >= 6): - out += B64(ch >> (bits-6)) - bits -= 6 - return out, bits - -def PyUnicode_DecodeUTF7(s, size, errors): - from _codecs import lookup_error - errmsg = "" - inShift = 0 - bitsleft = 0 - charsleft = 0 - surrogate = 0 - startinpos = 0 - p = [] - errorHandler = None - exc = None - - if (size == 0): - return unicode('') - i = 0 - while i < size: - - ch = s[i] - if (inShift): - if ((ch == '-') or not B64CHAR(ch)): - inShift = 0 - i += 1 - - while (bitsleft >= 16): - outCh = ((charsleft) >> (bitsleft-16)) & 0xffff - bitsleft -= 16 - - if (surrogate): - ## We have already generated an error for the high surrogate - ## so let's not bother seeing if the low surrogate is correct or not - surrogate = 0 - elif (0xDC00 <= (outCh) and (outCh) <= 0xDFFF): - ## This is a surrogate pair. Unfortunately we can't represent - ## it in a 16-bit character - surrogate = 1 - msg = "code pairs are not supported" - out, i = unicode_call_errorhandler(errors, 'utf-7', msg, s, i-1, i) - p += out - bitsleft = 0 - break - else: - p += unichr(outCh ) - #p += out - if (bitsleft >= 6): -## /* The shift sequence has a partial character in it. If -## bitsleft < 6 then we could just classify it as padding -## but that is not the case here */ - msg = "partial character in shift sequence" - out, i = unicode_call_errorhandler(errors, 'utf-7', msg, s, i-1, i) - -## /* According to RFC2152 the remaining bits should be zero. We -## choose to signal an error/insert a replacement character -## here so indicate the potential of a misencoded character. */ - -## /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ -## if (bitsleft and (charsleft << (sizeof(charsleft) * 8 - bitsleft))): -## raise UnicodeDecodeError, "non-zero padding bits in shift sequence" - if (ch == '-') : - if ((i < size) and (s[i] == '-')) : - p += '-' - inShift = 1 - - elif SPECIAL(ch, 0, 0) : - msg = "unexpected special character" - out, i = unicode_call_errorhandler(errors, 'utf-7', msg, s, i-1, i) - p += out - else: - p += ch - else: - charsleft = (charsleft << 6) | UB64(ch) - bitsleft += 6 - i += 1 -## /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); - elif ( ch == '+' ): - startinpos = i - i += 1 - if (i 0 - else: - out += chr(ord(ch)) - else: - if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)): - out += B64((charsleft) << (6-bitsleft)) - charsleft = 0 - bitsleft = 0 -## /* Characters not in the BASE64 set implicitly unshift the sequence -## so no '-' is required, except if the character is itself a '-' */ - if (B64CHAR(ch) or ch == '-'): - out += '-' - inShift = False - out += chr(ord(ch)) - else: - bitsleft += 16 - charsleft = (((charsleft) << 16) | ord(ch)) - p, bitsleft = ENCODE(charsleft, bitsleft) - out += p -## /* If the next character is special then we dont' need to terminate -## the shift sequence. If the next character is not a BASE64 character -## or '-' then the shift sequence will be terminated implicitly and we -## don't have to insert a '-'. */ - - if (bitsleft == 0): - if (i + 1 < size): - ch2 = s[i+1] - - if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)): - pass - elif (B64CHAR(ch2) or ch2 == '-'): - out += '-' - inShift = False - else: - inShift = False - else: - out += '-' - inShift = False - i += 1 - - if (bitsleft): - out += B64(charsleft << (6-bitsleft) ) - out += '-' - - return out - -unicode_empty = u'' - def unicode_call_errorhandler(errors, encoding, reason, input, startinpos, endinpos, decode=True): Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Mon Jun 28 18:53:42 2010 @@ -368,6 +368,7 @@ for encoders in [ "ascii_encode", "latin_1_encode", + "utf_7_encode", "utf_8_encode", "utf_16_encode", "utf_16_be_encode", @@ -380,6 +381,7 @@ for decoders in [ "ascii_decode", "latin_1_decode", + "utf_7_decode", "utf_8_decode", "utf_16_decode", "utf_16_be_decode", Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Mon Jun 28 18:53:42 2010 @@ -418,6 +418,228 @@ # ____________________________________________________________ +# utf-7 + +## indicate whether a UTF-7 character is special i.e. cannot be directly +## encoded: +## 0 - not special +## 1 - special +## 2 - whitespace (optional) +## 3 - RFC2152 Set O (optional) + +_utf7_special = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, +] + +def _utf7_SPECIAL(oc, encodeO=False, encodeWS=False): + return (oc > 127 or _utf7_special[oc] == 1 or + (encodeWS and _utf7_special[oc] == 2) or + (encodeO and _utf7_special[oc] == 3)) + +def _utf7_B64CHAR(oc): + if oc > 127: + return False + c = chr(oc) + return c.isalnum() or c == '+' or c == '/' +def _utf7_TO_BASE64(n): + "Returns the base-64 character of the bottom 6 bits of n" + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[n & 0x3f] +def _utf7_FROM_BASE64(c): + "Retuns the base-64 value of a base-64 character" + if c == '+': + return 62 + elif c == '/': + return 63 + elif c >= 'a': + return ord(c) - 71 + elif c >= 'A': + return ord(c) - 65 + else: + return ord(c) + 4 + +def _utf7_ENCODE(result, ch, bits) : + while (bits >= 6): + result.append(_utf7_TO_BASE64(ch >> (bits - 6))) + bits -= 6 + return bits + +def str_decode_utf_7(s, size, errors, final=False, + errorhandler=None): + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + if (size == 0): + return u'', 0 + + inShift = False + bitsleft = 0 + startinpos = 0 + charsleft = 0 + surrogate = False + + result = UnicodeBuilder(size) + pos = 0 + while pos < size: + ch = s[pos] + oc = ord(ch) + + if inShift: + if ch == '-' or not _utf7_B64CHAR(oc): + inShift = 0 + pos += 1 + + while bitsleft >= 16: + outCh = (charsleft >> (bitsleft-16)) & 0xffff + bitsleft -= 16 + + if surrogate: + ## We have already generated an error for the high + ## surrogate so let's not bother seeing if the low + ## surrogate is correct or not + surrogate = False + elif 0xDC00 <= outCh <= 0xDFFF: + ## This is a surrogate pair. Unfortunately we can't + ## represent it in a 16-bit character + surrogate = True + msg = "code pairs are not supported" + res, pos = errorhandler(errors, 'utf-7', + msg, s, pos-1, pos) + result.append(res) + bitsleft = 0 + break + else: + result.append(unichr(outCh)) + if bitsleft >= 6: + ## The shift sequence has a partial character in it. If + ## bitsleft < 6 then we could just classify it as padding + ## but that is not the case here + msg = "partial character in shift sequence" + res, pos = errorhandler(errors, 'utf-7', + msg, s, pos-1, pos) + result.append(res) + ## According to RFC2152 the remaining bits should be + ## zero. We choose to signal an error/insert a replacement + ## character here so indicate the potential of a + ## misencoded character. + if ch == '-': + if pos < size and s[pos] == '-': + result.append(u'-') + inShift = True + + elif _utf7_SPECIAL(oc) : + msg = "unexpected special character" + res, pos = errorhandler(errors, 'utf-7', + msg, s, pos-1, pos) + result.append(res) + else: + result.append(unichr(ord(ch))) + else: + charsleft = (charsleft << 6) | _utf7_FROM_BASE64(ch) + bitsleft += 6 + pos += 1 + elif ch == '+': + startinpos = pos + pos += 1 + if pos < size and s[pos] == '-': + pos += 1 + result.append(u'+') + else: + inShift = 1 + bitsleft = 0 + + elif _utf7_SPECIAL(oc): + pos += 1 + msg = "unexpected special character" + res, pos = errorhandler(errors, 'utf-7', msg, s, pos-1, pos) + result.append(res) + else: + result.append(unichr(oc)) + pos += 1 + + if inShift: + endinpos = size + msg = "unterminated shift sequence" + res, pos = errorhandler(errors, 'utf-7', msg, s, startinpos, pos) + result.append(res) + + return result.build(), pos + +def unicode_encode_utf_7(s, size, errors, errorhandler=None): + if (size == 0): + return '' + result = StringBuilder(size) + + encodeSetO = encodeWhiteSpace = False + + inShift = False + bitsleft = 0 + charsleft = 0 + + pos = 0 + while pos < size: + ch = s[pos] + oc = ord(ch) + if not inShift: + if ch == u'+': + result.append('+-') + elif _utf7_SPECIAL(oc, encodeSetO, encodeWhiteSpace): + charsleft = oc + bitsleft = 16 + result.append('+') + bitsleft = _utf7_ENCODE(result, charsleft, bitsleft) + inShift = bitsleft > 0 + else: + result.append(chr(oc)) + else: + if not _utf7_SPECIAL(oc, encodeSetO, encodeWhiteSpace): + result.append(_utf7_TO_BASE64(charsleft << (6-bitsleft))) + charsleft = 0 + bitsleft = 0 + ## Characters not in the BASE64 set implicitly unshift the + ## sequence so no '-' is required, except if the character is + ## itself a '-' + if _utf7_B64CHAR(oc) or ch == u'-': + result.append('-') + inShift = False + result.append(chr(oc)) + else: + bitsleft += 16 + charsleft = (charsleft << 16) | oc + bitsleft = _utf7_ENCODE(result, charsleft, bitsleft) + ## If the next character is special then we dont' need to + ## terminate the shift sequence. If the next character is not + ## a BASE64 character or '-' then the shift sequence will be + ## terminated implicitly and we don't have to insert a '-'. + if bitsleft == 0: + if pos + 1 < size: + ch2 = s[pos + 1] + oc2 = ord(ch2) + + if (_utf7_SPECIAL(oc2, encodeSetO, encodeWhiteSpace)): + pass + elif (_utf7_B64CHAR(oc2) or ch2 == u'-'): + result.append('-') + inShift = False + else: + inShift = False + else: + result.append('-') + inShift = False + pos += 1 + + if bitsleft: + result.append(_utf7_TO_BASE64(charsleft << (6 - bitsleft))) + result.append('-') + + return result.build() + +# ____________________________________________________________ # ascii and latin-1 def str_decode_latin_1(s, size, errors, final=False, @@ -563,7 +785,7 @@ ch = s[pos] pos += 1 - # \x escapes */ + # \x escapes if ch == '\n': pass elif ch == '\\': builder.append(u'\\') elif ch == '\'': builder.append(u'\'') @@ -697,7 +919,7 @@ pos += 1 oc2 = ord(s[pos]) - if 0xDC00 <= oc2 < 0xDFFF: + if 0xDC00 <= oc2 <= 0xDFFF: ucs = (((oc & 0x03FF) << 10) | (oc2 & 0x03FF)) + 0x00010000 raw_unicode_escape_helper(result, ucs) pos += 1 From getxsick at codespeak.net Mon Jun 28 19:50:17 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 19:50:17 +0200 (CEST) Subject: [pypy-svn] r75645 - pypy/build/ubuntu/1.3.0 Message-ID: <20100628175017.0154D282B90@codespeak.net> Author: getxsick Date: Mon Jun 28 19:50:15 2010 New Revision: 75645 Added: pypy/build/ubuntu/1.3.0/ - copied from r75644, pypy/build/ubuntu/1.2.0/ Log: create build scripts for PyPy 1.3.0 From getxsick at codespeak.net Mon Jun 28 19:55:56 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 19:55:56 +0200 (CEST) Subject: [pypy-svn] r75646 - pypy/build/ubuntu/1.3.0/debian Message-ID: <20100628175556.7B914282B90@codespeak.net> Author: getxsick Date: Mon Jun 28 19:55:54 2010 New Revision: 75646 Modified: pypy/build/ubuntu/1.3.0/debian/rules Log: update version to 1.3 Modified: pypy/build/ubuntu/1.3.0/debian/rules ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/rules (original) +++ pypy/build/ubuntu/1.3.0/debian/rules Mon Jun 28 19:55:54 2010 @@ -9,15 +9,15 @@ DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH) DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) -VERSION=1.2 +VERSION=1.3 get-orig-source: set -e ; \ - svn co http://codespeak.net/svn/pypy/release/1.2.0 pypy-1.2.0 ; \ - REVISION=`svnversion pypy-1.2.0/` ; \ - find pypy-1.2.0/ -depth -type d -name ".svn" | xargs rm -rf ; \ - tar cfz pypy_$(VERSION).0.orig.tar.gz pypy-1.2.0/ ; \ - rm -rf pypy-1.2.0/ + svn co http://codespeak.net/svn/pypy/release/1.3.0 pypy-1.3.0 ; \ + REVISION=`svnversion pypy-1.3.0/` ; \ + find pypy-1.3.0/ -depth -type d -name ".svn" | xargs rm -rf ; \ + tar cfz pypy_$(VERSION).0.orig.tar.gz pypy-1.3.0/ ; \ + rm -rf pypy-1.3.0/ Makefile: debian/Makefile.in python debian/configure.py --build=$(DEB_BUILD_ARCH) --host=$(DEB_HOST_ARCH) --prefix=debian/tmp/usr debian/Makefile.in From getxsick at codespeak.net Mon Jun 28 20:32:49 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 20:32:49 +0200 (CEST) Subject: [pypy-svn] r75647 - in pypy/build/ubuntu/1.3.0/debian: . scripts Message-ID: <20100628183249.D72B5282B9D@codespeak.net> Author: getxsick Date: Mon Jun 28 20:32:46 2010 New Revision: 75647 Modified: pypy/build/ubuntu/1.3.0/debian/pypy-dev.install pypy/build/ubuntu/1.3.0/debian/pypy-dev.links pypy/build/ubuntu/1.3.0/debian/pypy-dotviewer.install pypy/build/ubuntu/1.3.0/debian/pypy-lib.install pypy/build/ubuntu/1.3.0/debian/pypy-lib.links pypy/build/ubuntu/1.3.0/debian/scripts/dotviewer pypy/build/ubuntu/1.3.0/debian/scripts/rpycompile pypy/build/ubuntu/1.3.0/debian/scripts/sshgraphserver Log: update 1.2 to 1.3 Modified: pypy/build/ubuntu/1.3.0/debian/pypy-dev.install ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/pypy-dev.install (original) +++ pypy/build/ubuntu/1.3.0/debian/pypy-dev.install Mon Jun 28 20:32:46 2010 @@ -1,17 +1,17 @@ -pypy/annotation usr/share/pypy-1.2/pypy -pypy/bin usr/share/pypy-1.2/pypy -pypy/config usr/share/pypy-1.2/pypy -pypy/__init__.py usr/share/pypy-1.2/pypy -pypy/interpreter usr/share/pypy-1.2/pypy -pypy/jit usr/share/pypy-1.2/pypy -pypy/module usr/share/pypy-1.2/pypy -pypy/objspace usr/share/pypy-1.2/pypy -pypy/rlib usr/share/pypy-1.2/pypy -pypy/rpython usr/share/pypy-1.2/pypy -pypy/tool usr/share/pypy-1.2/pypy -pypy/translator usr/share/pypy-1.2/pypy -pypy/conftest.py usr/share/pypy-1.2/pypy -py usr/share/pypy-1.2 -greenlet usr/share/pypy-1.2 -testrunner usr/share/pypy-1.2 +pypy/annotation usr/share/pypy-1.3/pypy +pypy/bin usr/share/pypy-1.3/pypy +pypy/config usr/share/pypy-1.3/pypy +pypy/__init__.py usr/share/pypy-1.3/pypy +pypy/interpreter usr/share/pypy-1.3/pypy +pypy/jit usr/share/pypy-1.3/pypy +pypy/module usr/share/pypy-1.3/pypy +pypy/objspace usr/share/pypy-1.3/pypy +pypy/rlib usr/share/pypy-1.3/pypy +pypy/rpython usr/share/pypy-1.3/pypy +pypy/tool usr/share/pypy-1.3/pypy +pypy/translator usr/share/pypy-1.3/pypy +pypy/conftest.py usr/share/pypy-1.3/pypy +py usr/share/pypy-1.3 +greenlet usr/share/pypy-1.3 +testrunner usr/share/pypy-1.3 debian/scripts/rpycompile usr/bin Modified: pypy/build/ubuntu/1.3.0/debian/pypy-dev.links ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/pypy-dev.links (original) +++ pypy/build/ubuntu/1.3.0/debian/pypy-dev.links Mon Jun 28 20:32:46 2010 @@ -1 +1 @@ -/var/cache/pypy/_cache /usr/share/pypy-1.2/pypy/_cache +/var/cache/pypy/_cache /usr/share/pypy-1.3/pypy/_cache Modified: pypy/build/ubuntu/1.3.0/debian/pypy-dotviewer.install ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/pypy-dotviewer.install (original) +++ pypy/build/ubuntu/1.3.0/debian/pypy-dotviewer.install Mon Jun 28 20:32:46 2010 @@ -1,3 +1,3 @@ -dotviewer usr/share/pypy-1.2 +dotviewer usr/share/pypy-1.3 debian/scripts/dotviewer usr/bin debian/scripts/sshgraphserver usr/bin Modified: pypy/build/ubuntu/1.3.0/debian/pypy-lib.install ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/pypy-lib.install (original) +++ pypy/build/ubuntu/1.3.0/debian/pypy-lib.install Mon Jun 28 20:32:46 2010 @@ -1,2 +1,2 @@ -lib-python usr/share/pypy-1.2 -pypy/lib usr/share/pypy-1.2/pypy +lib-python usr/share/pypy-1.3 +pypy/lib usr/share/pypy-1.3/pypy Modified: pypy/build/ubuntu/1.3.0/debian/pypy-lib.links ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/pypy-lib.links (original) +++ pypy/build/ubuntu/1.3.0/debian/pypy-lib.links Mon Jun 28 20:32:46 2010 @@ -1 +1 @@ -usr/share/pypy-1.2/pypy/lib usr/share/pypy-1.2/lib +usr/share/pypy-1.3/pypy/lib usr/share/pypy-1.3/lib Modified: pypy/build/ubuntu/1.3.0/debian/scripts/dotviewer ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/scripts/dotviewer (original) +++ pypy/build/ubuntu/1.3.0/debian/scripts/dotviewer Mon Jun 28 20:32:46 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/dotviewer/dotviewer.py "$@" +/usr/share/pypy-1.3/dotviewer/dotviewer.py "$@" Modified: pypy/build/ubuntu/1.3.0/debian/scripts/rpycompile ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/scripts/rpycompile (original) +++ pypy/build/ubuntu/1.3.0/debian/scripts/rpycompile Mon Jun 28 20:32:46 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/pypy/translator/goal/translate.py "$@" +/usr/share/pypy-1.3/pypy/translator/goal/translate.py "$@" Modified: pypy/build/ubuntu/1.3.0/debian/scripts/sshgraphserver ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/scripts/sshgraphserver (original) +++ pypy/build/ubuntu/1.3.0/debian/scripts/sshgraphserver Mon Jun 28 20:32:46 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/dotviewer/sshgraphserver.py "$@" +/usr/share/pypy-1.3/dotviewer/sshgraphserver.py "$@" From getxsick at codespeak.net Mon Jun 28 20:36:57 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 20:36:57 +0200 (CEST) Subject: [pypy-svn] r75648 - pypy/build/ubuntu/1.3.0/debian Message-ID: <20100628183657.9AC7F282B9D@codespeak.net> Author: getxsick Date: Mon Jun 28 20:36:55 2010 New Revision: 75648 Modified: pypy/build/ubuntu/1.3.0/debian/changelog Log: add new entry to the changelog Modified: pypy/build/ubuntu/1.3.0/debian/changelog ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/changelog (original) +++ pypy/build/ubuntu/1.3.0/debian/changelog Mon Jun 28 20:36:55 2010 @@ -1,3 +1,9 @@ +pypy (1.3.0-ppa1+lucid1) lucid; urgency=low + + * New upstream release. + + -- Bartosz Skowron Mon, 28 Jun 2010 20:02:10 +0200 + pypy (1.2.0-ppa1+karmic9) karmic; urgency=low * Fix failing tests. From getxsick at codespeak.net Mon Jun 28 20:48:40 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 20:48:40 +0200 (CEST) Subject: [pypy-svn] r75649 - pypy/build/ubuntu/1.3.0/debian Message-ID: <20100628184840.A310E282B9D@codespeak.net> Author: getxsick Date: Mon Jun 28 20:48:38 2010 New Revision: 75649 Modified: pypy/build/ubuntu/1.3.0/debian/rules Log: kill removing pypy/translator/c/winproj/ it's already removed from the pypy repository Modified: pypy/build/ubuntu/1.3.0/debian/rules ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/rules (original) +++ pypy/build/ubuntu/1.3.0/debian/rules Mon Jun 28 20:48:38 2010 @@ -55,7 +55,6 @@ rm debian/pypy-dev/usr/share/pypy-$(VERSION)/pypy/module/unicodedata/LICENSE rm debian/pypy-lib/usr/share/pypy-$(VERSION)/pypy/lib/py rm debian/pypy-lib/usr/share/pypy-$(VERSION)/pypy/lib/app_test/ctypes_tests/_ctypes_test.o - rm -r debian/pypy-dev/usr/share/pypy-$(VERSION)/pypy/translator/c/winproj/ chmod a-x debian/pypy-lib/usr/share/pypy-$(VERSION)/lib-python/2.5.2/idlelib/idle.bat install-arch: From getxsick at codespeak.net Mon Jun 28 20:55:33 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 20:55:33 +0200 (CEST) Subject: [pypy-svn] r75650 - pypy/build/ubuntu/1.3.0/debian Message-ID: <20100628185533.1D9EE282B9D@codespeak.net> Author: getxsick Date: Mon Jun 28 20:55:31 2010 New Revision: 75650 Modified: pypy/build/ubuntu/1.3.0/debian/changelog Log: update the upstream version in the changelog Modified: pypy/build/ubuntu/1.3.0/debian/changelog ============================================================================== --- pypy/build/ubuntu/1.3.0/debian/changelog (original) +++ pypy/build/ubuntu/1.3.0/debian/changelog Mon Jun 28 20:55:31 2010 @@ -1,4 +1,4 @@ -pypy (1.3.0-ppa1+lucid1) lucid; urgency=low +pypy (1.3.0-ppa1+lucid2) lucid; urgency=low * New upstream release. From getxsick at codespeak.net Mon Jun 28 21:03:17 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 21:03:17 +0200 (CEST) Subject: [pypy-svn] r75651 - in pypy/build/ubuntu/trunk/debian: . scripts Message-ID: <20100628190317.83F1B282BAD@codespeak.net> Author: getxsick Date: Mon Jun 28 21:02:43 2010 New Revision: 75651 Modified: pypy/build/ubuntu/trunk/debian/pypy-dev.install pypy/build/ubuntu/trunk/debian/pypy-dev.links pypy/build/ubuntu/trunk/debian/pypy-dotviewer.install pypy/build/ubuntu/trunk/debian/pypy-lib.install pypy/build/ubuntu/trunk/debian/pypy-lib.links pypy/build/ubuntu/trunk/debian/rules pypy/build/ubuntu/trunk/debian/scripts/dotviewer pypy/build/ubuntu/trunk/debian/scripts/rpycompile pypy/build/ubuntu/trunk/debian/scripts/sshgraphserver Log: update pypy version to 1.3 for weekly builds Modified: pypy/build/ubuntu/trunk/debian/pypy-dev.install ============================================================================== --- pypy/build/ubuntu/trunk/debian/pypy-dev.install (original) +++ pypy/build/ubuntu/trunk/debian/pypy-dev.install Mon Jun 28 21:02:43 2010 @@ -1,17 +1,17 @@ -pypy/annotation usr/share/pypy-1.2/pypy -pypy/bin usr/share/pypy-1.2/pypy -pypy/config usr/share/pypy-1.2/pypy -pypy/__init__.py usr/share/pypy-1.2/pypy -pypy/interpreter usr/share/pypy-1.2/pypy -pypy/jit usr/share/pypy-1.2/pypy -pypy/module usr/share/pypy-1.2/pypy -pypy/objspace usr/share/pypy-1.2/pypy -pypy/rlib usr/share/pypy-1.2/pypy -pypy/rpython usr/share/pypy-1.2/pypy -pypy/tool usr/share/pypy-1.2/pypy -pypy/translator usr/share/pypy-1.2/pypy -pypy/conftest.py usr/share/pypy-1.2/pypy -py usr/share/pypy-1.2 -greenlet usr/share/pypy-1.2 -testrunner usr/share/pypy-1.2 +pypy/annotation usr/share/pypy-1.3/pypy +pypy/bin usr/share/pypy-1.3/pypy +pypy/config usr/share/pypy-1.3/pypy +pypy/__init__.py usr/share/pypy-1.3/pypy +pypy/interpreter usr/share/pypy-1.3/pypy +pypy/jit usr/share/pypy-1.3/pypy +pypy/module usr/share/pypy-1.3/pypy +pypy/objspace usr/share/pypy-1.3/pypy +pypy/rlib usr/share/pypy-1.3/pypy +pypy/rpython usr/share/pypy-1.3/pypy +pypy/tool usr/share/pypy-1.3/pypy +pypy/translator usr/share/pypy-1.3/pypy +pypy/conftest.py usr/share/pypy-1.3/pypy +py usr/share/pypy-1.3 +greenlet usr/share/pypy-1.3 +testrunner usr/share/pypy-1.3 debian/scripts/rpycompile usr/bin Modified: pypy/build/ubuntu/trunk/debian/pypy-dev.links ============================================================================== --- pypy/build/ubuntu/trunk/debian/pypy-dev.links (original) +++ pypy/build/ubuntu/trunk/debian/pypy-dev.links Mon Jun 28 21:02:43 2010 @@ -1 +1 @@ -/var/cache/pypy/_cache /usr/share/pypy-1.2/pypy/_cache +/var/cache/pypy/_cache /usr/share/pypy-1.3/pypy/_cache Modified: pypy/build/ubuntu/trunk/debian/pypy-dotviewer.install ============================================================================== --- pypy/build/ubuntu/trunk/debian/pypy-dotviewer.install (original) +++ pypy/build/ubuntu/trunk/debian/pypy-dotviewer.install Mon Jun 28 21:02:43 2010 @@ -1,3 +1,3 @@ -dotviewer usr/share/pypy-1.2 +dotviewer usr/share/pypy-1.3 debian/scripts/dotviewer usr/bin debian/scripts/sshgraphserver usr/bin Modified: pypy/build/ubuntu/trunk/debian/pypy-lib.install ============================================================================== --- pypy/build/ubuntu/trunk/debian/pypy-lib.install (original) +++ pypy/build/ubuntu/trunk/debian/pypy-lib.install Mon Jun 28 21:02:43 2010 @@ -1,2 +1,2 @@ -lib-python usr/share/pypy-1.2 -pypy/lib usr/share/pypy-1.2/pypy +lib-python usr/share/pypy-1.3 +pypy/lib usr/share/pypy-1.3/pypy Modified: pypy/build/ubuntu/trunk/debian/pypy-lib.links ============================================================================== --- pypy/build/ubuntu/trunk/debian/pypy-lib.links (original) +++ pypy/build/ubuntu/trunk/debian/pypy-lib.links Mon Jun 28 21:02:43 2010 @@ -1 +1 @@ -usr/share/pypy-1.2/pypy/lib usr/share/pypy-1.2/lib +usr/share/pypy-1.3/pypy/lib usr/share/pypy-1.3/lib Modified: pypy/build/ubuntu/trunk/debian/rules ============================================================================== --- pypy/build/ubuntu/trunk/debian/rules (original) +++ pypy/build/ubuntu/trunk/debian/rules Mon Jun 28 21:02:43 2010 @@ -9,7 +9,7 @@ DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH) DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) -VERSION=1.2 +VERSION=1.3 get-orig-source: set -e ; \ Modified: pypy/build/ubuntu/trunk/debian/scripts/dotviewer ============================================================================== --- pypy/build/ubuntu/trunk/debian/scripts/dotviewer (original) +++ pypy/build/ubuntu/trunk/debian/scripts/dotviewer Mon Jun 28 21:02:43 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/dotviewer/dotviewer.py "$@" +/usr/share/pypy-1.3/dotviewer/dotviewer.py "$@" Modified: pypy/build/ubuntu/trunk/debian/scripts/rpycompile ============================================================================== --- pypy/build/ubuntu/trunk/debian/scripts/rpycompile (original) +++ pypy/build/ubuntu/trunk/debian/scripts/rpycompile Mon Jun 28 21:02:43 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/pypy/translator/goal/translate.py "$@" +/usr/share/pypy-1.3/pypy/translator/goal/translate.py "$@" Modified: pypy/build/ubuntu/trunk/debian/scripts/sshgraphserver ============================================================================== --- pypy/build/ubuntu/trunk/debian/scripts/sshgraphserver (original) +++ pypy/build/ubuntu/trunk/debian/scripts/sshgraphserver Mon Jun 28 21:02:43 2010 @@ -1,3 +1,3 @@ #!/bin/sh -/usr/share/pypy-1.2/dotviewer/sshgraphserver.py "$@" +/usr/share/pypy-1.3/dotviewer/sshgraphserver.py "$@" From getxsick at codespeak.net Mon Jun 28 21:05:46 2010 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Mon, 28 Jun 2010 21:05:46 +0200 (CEST) Subject: [pypy-svn] r75652 - pypy/build/ubuntu/trunk Message-ID: <20100628190546.39F95282B9D@codespeak.net> Author: getxsick Date: Mon Jun 28 21:04:56 2010 New Revision: 75652 Modified: pypy/build/ubuntu/trunk/autobuild.sh Log: update the upstream version to pre-1.4 Modified: pypy/build/ubuntu/trunk/autobuild.sh ============================================================================== --- pypy/build/ubuntu/trunk/autobuild.sh (original) +++ pypy/build/ubuntu/trunk/autobuild.sh Mon Jun 28 21:04:56 2010 @@ -4,7 +4,7 @@ # LOGFILE="autobuild.log" -NEXT_RELEASE=1.3 +NEXT_RELEASE=1.4 export DEBFULLNAME="Bartosz Skowron's Daily Debs" export DEBEMAIL="getxsick at gmail.com" From benjamin at codespeak.net Mon Jun 28 22:12:22 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 28 Jun 2010 22:12:22 +0200 (CEST) Subject: [pypy-svn] r75653 - in pypy/branch/fast-forward/pypy: interpreter objspace objspace/flow objspace/std objspace/test translator Message-ID: <20100628201222.0BCF0282B9D@codespeak.net> Author: benjamin Date: Mon Jun 28 22:12:19 2010 New Revision: 75653 Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py pypy/branch/fast-forward/pypy/objspace/descroperation.py pypy/branch/fast-forward/pypy/objspace/flow/operation.py pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py pypy/branch/fast-forward/pypy/objspace/std/typeobject.py pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py pypy/branch/fast-forward/pypy/translator/geninterplevel.py Log: support __subclasscheck__ and __instancecheck__ Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Mon Jun 28 22:12:19 2010 @@ -870,10 +870,6 @@ return self.w_True return self.w_False - def isinstance(self, w_obj, w_type): - w_objtype = self.type(w_obj) - return self.issubtype(w_objtype, w_type) - def isinstance_w(self, w_obj, w_type): return self.is_true(self.isinstance(w_obj, w_type)) @@ -904,7 +900,7 @@ # it with exception_ def exception_is_valid_obj_as_class_w(self, w_obj): - if not self.is_true(self.isinstance(w_obj, self.w_type)): + if not self.isinstance_w(w_obj, self.w_type): return False if not self.full_exceptions: return True @@ -1201,7 +1197,8 @@ ('is_', 'is', 2, []), ('id', 'id', 1, []), ('type', 'type', 1, []), - ('issubtype', 'issubtype', 2, []), # not for old-style classes + ('isinstance', 'isinstance', 2, ['__instancecheck__']), + ('issubtype', 'issubtype', 2, ['__subclasscheck__']), # not for old-style classes ('repr', 'repr', 1, ['__repr__']), ('str', 'str', 1, ['__str__']), ('format', 'format', 2, ['__format__']), Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/descroperation.py Mon Jun 28 22:12:19 2010 @@ -464,10 +464,19 @@ raise OperationError(space.w_TypeError, space.wrap("coercion should return None or 2-tuple")) return w_res - + def issubtype(space, w_sub, w_type): + w_check = space.lookup(w_type, "__subclasscheck__") + if w_check is None: + raise OperationError(space.w_TypeError, + space.wrap("issubclass not supported here")) + return space.get_and_call_function(w_check, w_type, w_sub) - # xxx ord + def isinstance(space, w_inst, w_type): + w_check = space.lookup(w_type, "__instancecheck__") + if w_check is not None: + return space.get_and_call_function(w_check, w_type, w_inst) + return space.issubtype(space.type(w_inst), w_type) Modified: pypy/branch/fast-forward/pypy/objspace/flow/operation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/flow/operation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/flow/operation.py Mon Jun 28 22:12:19 2010 @@ -174,6 +174,7 @@ ('id', id), ('type', new_style_type), ('type', type), + ('isinstance', isinstance), ('issubtype', issubclass), ('repr', repr), ('str', str), Modified: pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py Mon Jun 28 22:12:19 2010 @@ -39,6 +39,7 @@ 'abs', 'hex', 'oct', # rare stuff? 'pos', 'divmod', 'cmp', # rare stuff? 'float', 'long', 'coerce', # rare stuff? + 'isinstance', 'issubtype', ] # We cannot support {get,set,del}slice right now because # DescrOperation.{get,set,del}slice do a bit more work than just call Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Mon Jun 28 22:12:19 2010 @@ -321,7 +321,7 @@ raise operationerrfmt(space.w_TypeError, "X is not a type object ('%s')", space.type(w_subtype).getname(space, '?')) - if not space.is_true(space.issubtype(w_subtype, w_self)): + if not w_subtype.issubtype(w_self): raise operationerrfmt(space.w_TypeError, "%s.__new__(%s): %s is not a subtype of %s", w_self.name, w_subtype.name, w_subtype.name, w_self.name) @@ -358,6 +358,17 @@ def is_cpytype(w_self): return w_self.__flags__ & _CPYTYPE + def issubtype(w_self, w_type): + w_self = hint(w_self, promote=True) + w_type = hint(w_type, promote=True) + if w_self.space.config.objspace.std.withtypeversion and we_are_jitted(): + version_tag1 = w_self.version_tag() + version_tag2 = w_type.version_tag() + if version_tag1 is not None and version_tag2 is not None: + res = _pure_issubtype(w_self, w_type, version_tag1, version_tag2) + return res + return _issubtype(w_self, w_type) + def get_module(w_self): space = w_self.space if w_self.is_heaptype() and '__module__' in w_self.dict_w: @@ -700,24 +711,18 @@ space.wrap("__init__() should return None")) return w_newobject -def _issubtype(w_type1, w_type2): - return w_type2 in w_type1.mro_w +def _issubtype(w_sub, w_type): + return w_type in w_sub.mro_w @purefunction_promote() -def _pure_issubtype(w_type1, w_type2, version_tag1, version_tag2): - return _issubtype(w_type1, w_type2) +def _pure_issubtype(w_sub, w_type, version_tag1, version_tag2): + return _issubtype(w_sub, w_type) + +def issubtype__Type_Type(space, w_type, w_sub): + return space.newbool(w_sub.issubtype(w_type)) -def issubtype__Type_Type(space, w_type1, w_type2): - w_type1 = hint(w_type1, promote=True) - w_type2 = hint(w_type2, promote=True) - if space.config.objspace.std.withtypeversion and we_are_jitted(): - version_tag1 = w_type1.version_tag() - version_tag2 = w_type2.version_tag() - if version_tag1 is not None and version_tag2 is not None: - res = _pure_issubtype(w_type1, w_type2, version_tag1, version_tag2) - return space.newbool(res) - res = _issubtype(w_type1, w_type2) - return space.newbool(res) +def isinstance__Type_ANY(space, w_type, w_inst): + return space.newbool(space.type(w_inst).issubtype(w_type)) def repr__Type(space, w_obj): w_mod = w_obj.get_module() Modified: pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py Mon Jun 28 22:12:19 2010 @@ -463,6 +463,33 @@ return self raises(TypeError, iter, x()) + def test_isinstance_and_issubclass(self): + class Meta(type): + def __instancecheck__(cls, instance): + if cls is A: + return True + return False + def __subclasscheck__(cls, sub): + if cls is B: + return True + return False + class A: + __metaclass__ = Meta + class B(A): + pass + a = A() + b = B() + assert isinstance(a, A) + assert not isinstance(a, B) + assert isinstance(b, A) + assert not isinstance(b, B) + assert isinstance(4, A) + assert not issubclass(A, A) + assert not issubclass(B, A) + assert issubclass(A, B) + assert issubclass(B, B) + assert issubclass(23, B) + class AppTestWithBuiltinShortcut(AppTest_Descroperation): OPTIONS = {'objspace.std.builtinshortcut': True} Modified: pypy/branch/fast-forward/pypy/translator/geninterplevel.py ============================================================================== --- pypy/branch/fast-forward/pypy/translator/geninterplevel.py (original) +++ pypy/branch/fast-forward/pypy/translator/geninterplevel.py Mon Jun 28 22:12:19 2010 @@ -225,13 +225,14 @@ return ", ".join(res) def oper(self, op, localscope): - if op.opname == 'issubtype': + if op.opname in ('issubtype', 'isinstance'): arg = op.args[1] if (not isinstance(arg, Constant) or not isinstance(arg.value, (type, types.ClassType))): - op = SpaceOperation("simple_call", - [Constant(issubclass)]+op.args, - op.result) + func = issubclass if op.opname == 'issubtype' else isinstance + op = SpaceOperation("simple_call", + [Constant(func)]+op.args, + op.result) if op.opname == "simple_call": v = op.args[0] space_shortcut = self.try_space_shortcut_for_builtin(v, len(op.args)-1, @@ -703,21 +704,15 @@ arities = self._space_arities = {} for name, sym, arity, specnames in self.space.MethodTable: arities[name] = arity - arities['isinstance'] = 2 + del arities["isinstance"] return self._space_arities def try_space_shortcut_for_builtin(self, v, nargs, args): if isinstance(v, Constant) and v.value in self.ibuiltin_ids: name = self.ibuiltin_ids[v.value].__name__ - if hasattr(self.space, name): - if self.space_arities().get(name, -1) == nargs: - if name != 'isinstance': - return "space.%s" % name - else: - arg = args[1] - if (isinstance(arg, Constant) - and isinstance(arg.value, (type, types.ClassType))): - return "space.isinstance" + if (hasattr(self.space, name) and + self.space_arities().get(name, -1) == nargs): + return "space.%s" % name return None def nameof_builtin_function_or_method(self, func): From benjamin at codespeak.net Tue Jun 29 00:01:14 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 29 Jun 2010 00:01:14 +0200 (CEST) Subject: [pypy-svn] r75654 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100628220114.E62A0282B9D@codespeak.net> Author: benjamin Date: Tue Jun 29 00:01:12 2010 New Revision: 75654 Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py Log: add default __subclasshook__ Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/objecttype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/objecttype.py Tue Jun 29 00:01:12 2010 @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.typedef import GetSetProperty, default_identity_hash from pypy.interpreter import gateway +from pypy.interpreter.argument import Arguments from pypy.interpreter.baseobjspace import ObjSpace from pypy.objspace.descroperation import Object from pypy.objspace.std.stdtypedef import StdTypeDef, no_hash_descr @@ -100,6 +101,9 @@ raise OperationError(space.w_TypeError, space.wrap(msg)) return space.format(w_as_str, w_format_spec) +def descr___subclasshook__(space, __args__): + return space.w_NotImplemented + app = gateway.applevel(r''' def reduce_1(obj, proto): @@ -191,6 +195,8 @@ unwrap_spec=[gateway.ObjSpace,gateway.W_Root,int]), __format__ = gateway.interp2app(descr___format__, unwrap_spec=[ObjSpace, gateway.W_Root, gateway.W_Root]), + __subclasshook__ = gateway.interp2app(descr___subclasshook__, unwrap_spec= + [ObjSpace, Arguments]), __init__ = gateway.interp2app(descr__init__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), ) Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_obj.py Tue Jun 29 00:01:12 2010 @@ -63,3 +63,8 @@ res = format(x(), u"") assert res == u"Pickle" assert isinstance(res, unicode) + + def test_subclasshook(self): + class x(object): + pass + assert x().__subclasshook__(object()) is NotImplemented From afa at codespeak.net Tue Jun 29 13:20:26 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 13:20:26 +0200 (CEST) Subject: [pypy-svn] r75655 - in pypy/branch/interplevel-codecs/pypy: module/_codecs module/_codecs/test rlib Message-ID: <20100629112026.015FA282BAD@codespeak.net> Author: afa Date: Tue Jun 29 13:20:24 2010 New Revision: 75655 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: rewrite the "charmap" codec at interp-level Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Tue Jun 29 13:20:24 2010 @@ -6,7 +6,6 @@ appleveldefs = { '__doc__' : 'app_codecs.__doc__', '__name__' : 'app_codecs.__name__', - 'charmap_encode' : 'app_codecs.charmap_encode', 'escape_decode' : 'app_codecs.escape_decode', 'escape_encode' : 'app_codecs.escape_encode', 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', @@ -40,6 +39,7 @@ 'charbuffer_encode': 'interp_codecs.buffer_encode', 'readbuffer_encode': 'interp_codecs.buffer_encode', 'charmap_decode' : 'interp_codecs.charmap_decode', + 'charmap_encode' : 'interp_codecs.charmap_encode', 'unicode_escape_decode' : 'interp_codecs.unicode_escape_decode', 'unicode_escape_encode' : 'interp_codecs.unicode_escape_encode', 'raw_unicode_escape_decode' : 'interp_codecs.raw_unicode_escape_decode', Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Tue Jun 29 13:20:24 2010 @@ -36,9 +36,6 @@ """ -# XXX move some of these functions to RPython (like charmap_encode, -# charmap_build) to make them faster - def escape_encode( obj, errors='strict'): """None """ @@ -46,13 +43,6 @@ v = s[1:-1] return v, len(v) -def charmap_encode(obj, errors='strict', mapping=None): - """None - """ - res = PyUnicode_EncodeCharmap(obj, mapping, errors) - res = ''.join(res) - return res, len(res) - def unicode_internal_encode( obj, errors='strict'): """None """ @@ -191,54 +181,6 @@ raise TypeError("encoding error handler must return (unicode, int) tuple, not %s" % repr(res)) - -def charmapencode_output(c, mapping): - - rep = mapping[c] - if isinstance(rep, int) or isinstance(rep, long): - if rep < 256: - return chr(rep) - else: - raise TypeError("character mapping must be in range(256)") - elif isinstance(rep, str): - return rep - elif rep == None: - raise KeyError("character maps to ") - else: - raise TypeError("character mapping must return integer, None or str") - -def PyUnicode_EncodeCharmap(p, mapping='latin-1', errors='strict'): - -## /* the following variable is used for caching string comparisons -## * -1=not initialized, 0=unknown, 1=strict, 2=replace, -## * 3=ignore, 4=xmlcharrefreplace */ - -# /* Default to Latin-1 */ - if mapping == None: - import _codecs - return _codecs.latin_1_encode(p, errors)[0] - size = len(p) - if (size == 0): - return '' - inpos = 0 - res = [] - while (inpos", p, inpos, inpos+1, False) - try: - res += [charmapencode_output(ord(y), mapping) for y in x[0]] - except KeyError: - raise UnicodeEncodeError("charmap", p, inpos, inpos+1, - "character maps to ") - inpos += 1 - return res - - def charmap_build(somestring): m = {} num = 0 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 13:20:24 2010 @@ -414,80 +414,128 @@ space.wrap(byteorder)]) utf_16_ex_decode.unwrap_spec = [ObjSpace, str, str, int, W_Root] -def _extract_from_mapping(space, mapping_w, w_mapping, ch): - if mapping_w is not None: +# ____________________________________________________________ +# Charmap + +class Charmap_Decode: + def __init__(self, space, w_mapping): + self.space = space + self.w_mapping = w_mapping + + # fast path for all the stuff in the encodings module + if space.is_true(space.isinstance(w_mapping, space.w_tuple)): + self.mapping_w = space.fixedview(w_mapping) + else: + self.mapping_w = None + + def get(self, ch, errorchar): + space = self.space + + # get the character from the mapping + if self.mapping_w is not None: + w_ch = self.mapping_w[ord(ch)] + else: + try: + w_ch = space.getitem(self.w_mapping, space.newint(ord(ch))) + except OperationError, e: + if not e.match(space, space.w_LookupError): + raise + return errorchar + + # Charmap may return a unicode string try: - return mapping_w[ord(ch)] - except IndexError: - pass - else: + x = space.unicode_w(w_ch) + except OperationError, e: + if not e.match(space, space.w_TypeError): + raise + else: + return x + + # Charmap may return a number + try: + x = space.int_w(w_ch) + except OperationError: + if not e.match(space, space.w_TypeError): + raise + else: + return unichr(x) + + # Charmap may return None + if space.is_w(w_ch, space.w_None): + return errorchar + + raise OperationError(space.w_TypeError, space.wrap("invalid mapping")) + +class Charmap_Encode: + def __init__(self, space, w_mapping): + self.space = space + self.w_mapping = w_mapping + + def get(self, ch, errorchar): + space = self.space + + # get the character from the mapping try: - return space.getitem(w_mapping, space.newint(ord(ch))) + w_ch = space.getitem(self.w_mapping, space.newint(ord(ch))) except OperationError, e: - if (not e.match(space, space.w_KeyError) and - not e.match(space, space.w_IndexError)): + if not e.match(space, space.w_LookupError): raise - pass + return errorchar -def _append_unicode(space, builder, w_x): - try: - x = space.unicode_w(w_x) - except OperationError, e: - if not e.match(space, space.w_TypeError): - raise - else: - if x != u"\ufffe": - builder.append(x) - return True - return False - try: - x = space.int_w(w_x) - except OperationError: - if not e.match(space, space.w_TypeError): - raise - else: - if x < 65536: - builder.append(unichr(x)) + # Charmap may return a string + try: + x = space.realstr_w(w_ch) + except OperationError, e: + if not e.match(space, space.w_TypeError): + raise else: - raise OperationError(space.w_TypeError, space.wrap("character mapping must be in range(65536)")) - return True - if not space.is_true(w_x): - return False - else: - raise OperationError(space.w_TypeError, space.w_None) + return x + + # Charmap may return a number + try: + x = space.int_w(w_ch) + except OperationError: + if not e.match(space, space.w_TypeError): + raise + else: + return chr(x) + + # Charmap may return None + if space.is_w(w_ch, space.w_None): + return errorchar + raise OperationError(space.w_TypeError, space.wrap("invalid mapping")) -def charmap_decode(space, s, errors="strict", w_mapping=None): - size = len(s) - # Default to Latin-1 - if space.is_true(space.is_(w_mapping, space.w_None)): - return latin_1_decode(space, s, errors, space.w_False) - if (size == 0): + at unwrap_spec(ObjSpace, str, str, W_Root) +def charmap_decode(space, string, errors="strict", w_mapping=None): + if len(string) == 0: return space.newtuple([space.wrap(u''), space.wrap(0)]) - - # fast path for all the stuff in the encodings module - if space.is_true(space.isinstance(w_mapping, space.w_tuple)): - mapping_w = space.fixedview(w_mapping) + + if space.is_w(w_mapping, space.w_None): + mapping = None else: - mapping_w = None + mapping = Charmap_Decode(space, w_mapping) - builder = UnicodeBuilder(size) - inpos = 0 - while (inpos < len(s)): - #/* Get mapping_w (char ordinal -> integer, Unicode char or None) */ - ch = s[inpos] - w_x = _extract_from_mapping(space, mapping_w, w_mapping, ch) - if w_x is not None and _append_unicode(space, builder, w_x): - inpos += 1 - continue - state = space.fromcache(CodecState) - next, inpos = state.decode_error_handler(errors, "charmap", - "character maps to ", s, inpos, inpos+1) - builder.append(next) - res = builder.build() - return space.newtuple([space.wrap(res), space.wrap(size)]) -charmap_decode.unwrap_spec = [ObjSpace, str, str, W_Root] + final = True + state = space.fromcache(CodecState) + result, consumed = runicode.str_decode_charmap( + string, len(string), errors, + final, state.decode_error_handler, mapping) + return space.newtuple([space.wrap(result), space.wrap(consumed)]) + + at unwrap_spec(ObjSpace, unicode, str, W_Root) +def charmap_encode(space, uni, errors="strict", w_mapping=None): + if space.is_w(w_mapping, space.w_None): + mapping = None + else: + mapping = Charmap_Encode(space, w_mapping) + + state = space.fromcache(CodecState) + result = runicode.unicode_encode_charmap( + uni, len(uni), errors, + state.encode_error_handler, mapping) + return space.newtuple([space.wrap(result), space.wrap(len(uni))]) # ____________________________________________________________ # Unicode escape Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Tue Jun 29 13:20:24 2010 @@ -1,6 +1,5 @@ import autopath from pypy.conftest import gettestobjspace -from pypy.module._codecs.app_codecs import charmap_encode class AppTestCodecs: @@ -377,6 +376,9 @@ def test_charmap_decode_1(self): import codecs + assert codecs.charmap_encode(u'xxx') == ('xxx', 3) + assert codecs.charmap_encode(u'xxx', 'strict', {ord('x'): 'XX'}) == ('XXXXXX', 3) + res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab") assert res == (u"ab\ufffd", 3) res = codecs.charmap_decode("\x00\x01\x02", "replace", u"ab\ufffe") @@ -556,9 +558,3 @@ assert u'caf\xe9'.encode('mbcs') == 'caf\xe9' assert u'\u040a'.encode('mbcs') == '?' # some cyrillic letter assert 'cafx\e9'.decode('mbcs') == u'cafx\e9' - - -class TestDirect: - def test_charmap_encode(self): - assert charmap_encode(u'xxx') == ('xxx', 3) - assert charmap_encode(u'xxx', 'strict', {ord('x'): 'XX'}) == ('XXXXXX', 6) Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Tue Jun 29 13:20:24 2010 @@ -1,7 +1,7 @@ import sys from pypy.rlib.bitmanipulation import splitter from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.rlib.rstring import StringBuilder, UnicodeBuilder if rffi.sizeof(lltype.UniChar) == 4: @@ -714,6 +714,65 @@ return res # ____________________________________________________________ +# Charmap + +ERROR_CHAR = u'\ufffe' + + at specialize.argtype(5) +def str_decode_charmap(s, size, errors, final=False, + errorhandler=None, mapping=None): + "mapping can be a rpython dictionary, or a dict-like object." + + # Default to Latin-1 + if mapping is None: + return str_decode_latin_1(s, size, errors, final=final, + errorhandler=errorhandler) + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + if size == 0: + return u'', 0 + + pos = 0 + result = UnicodeBuilder(size) + while pos < size: + ch = s[pos] + + c = mapping.get(ch, ERROR_CHAR) + if c == ERROR_CHAR: + r, pos = errorhandler(errors, "charmap", + "character maps to ", + s, pos, pos + 1) + result.append(r) + continue + result.append(c) + pos += 1 + return result.build(), pos + +def unicode_encode_charmap(s, size, errors, errorhandler=None, + mapping=None): + if mapping is None: + return unicode_encode_latin_1(s, size, errors, + errorhandler=errorhandler) + + if size == 0: + return '' + result = StringBuilder(size) + pos = 0 + while pos < size: + ch = s[pos] + + c = mapping.get(ch, '') + if len(c) == 0: + r, pos = errorhandler(errors, "charmap", + "character maps to ", + s, pos, pos + 1) + result.append(r) + continue + result.append(c) + pos += 1 + return result.build() + +# ____________________________________________________________ # Unicode escape hexdigits = "0123456789ABCDEFabcdef" From afa at codespeak.net Tue Jun 29 13:34:42 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 13:34:42 +0200 (CEST) Subject: [pypy-svn] r75656 - in pypy/branch/interplevel-codecs/pypy/module/_codecs: . test Message-ID: <20100629113442.F2796282BAD@codespeak.net> Author: afa Date: Tue Jun 29 13:34:41 2010 New Revision: 75656 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Log: rewrite charmap_build() at interp-level Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Tue Jun 29 13:34:41 2010 @@ -10,7 +10,6 @@ 'escape_encode' : 'app_codecs.escape_encode', 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', 'unicode_internal_encode' : 'app_codecs.unicode_internal_encode', - 'charmap_build' : 'app_codecs.charmap_build' } interpleveldefs = { 'encode': 'interp_codecs.encode', @@ -19,6 +18,7 @@ 'lookup_error': 'interp_codecs.lookup_error', 'register': 'interp_codecs.register_codec', 'register_error': 'interp_codecs.register_error', + 'charmap_build' : 'interp_codecs.charmap_build', # encoders and decoders 'ascii_decode' : 'interp_codecs.ascii_decode', Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Tue Jun 29 13:34:41 2010 @@ -180,13 +180,3 @@ else: raise TypeError("encoding error handler must return (unicode, int) tuple, not %s" % repr(res)) - -def charmap_build(somestring): - m = {} - num = 0 - for elem in somestring: - m[ord(elem)] = num - num += 1 - return m - - Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 13:34:41 2010 @@ -537,6 +537,16 @@ state.encode_error_handler, mapping) return space.newtuple([space.wrap(result), space.wrap(len(uni))]) + + at unwrap_spec(ObjSpace, unicode) +def charmap_build(space, chars): + # XXX CPython sometimes uses a three-level trie + w_charmap = space.newdict() + for num in range(len(chars)): + elem = chars[num] + space.setitem(w_charmap, space.newint(ord(elem)), space.newint(num)) + return w_charmap + # ____________________________________________________________ # Unicode escape Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Tue Jun 29 13:34:41 2010 @@ -532,6 +532,11 @@ def test_charmap_decode_2(self): assert 'foo'.decode('charmap') == 'foo' + def test_charmap_build(self): + import codecs + assert codecs.charmap_build(u'123456') == {49: 0, 50: 1, 51: 2, + 52: 3, 53: 4, 54: 5} + def test_utf7_start_end_in_exception(self): try: '+IC'.decode('utf-7') From afa at codespeak.net Tue Jun 29 14:11:50 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 14:11:50 +0200 (CEST) Subject: [pypy-svn] r75657 - in pypy/branch/interplevel-codecs/pypy: module/_codecs rlib Message-ID: <20100629121150.69F10282BAD@codespeak.net> Author: afa Date: Tue Jun 29 14:11:48 2010 New Revision: 75657 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: rewrite the unicode_internal codec Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Tue Jun 29 14:11:48 2010 @@ -8,8 +8,6 @@ '__name__' : 'app_codecs.__name__', 'escape_decode' : 'app_codecs.escape_decode', 'escape_encode' : 'app_codecs.escape_encode', - 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', - 'unicode_internal_encode' : 'app_codecs.unicode_internal_encode', } interpleveldefs = { 'encode': 'interp_codecs.encode', @@ -44,6 +42,8 @@ 'unicode_escape_encode' : 'interp_codecs.unicode_escape_encode', 'raw_unicode_escape_decode' : 'interp_codecs.raw_unicode_escape_decode', 'raw_unicode_escape_encode' : 'interp_codecs.raw_unicode_escape_encode', + 'unicode_internal_decode' : 'interp_codecs.unicode_internal_decode', + 'unicode_internal_encode' : 'interp_codecs.unicode_internal_encode', } def __init__(self, space, *args): Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Tue Jun 29 14:11:48 2010 @@ -43,71 +43,6 @@ v = s[1:-1] return v, len(v) -def unicode_internal_encode( obj, errors='strict'): - """None - """ - import sys - if sys.maxunicode == 65535: - unicode_bytes = 2 - else: - unicode_bytes = 4 - p = [] - for x in obj: - i = ord(x) - bytes = [] - for j in xrange(unicode_bytes): - bytes += chr(i%256) - i >>= 8 - if sys.byteorder == "big": - bytes.reverse() - p += bytes - res = ''.join(p) - return res, len(res) - -def unicode_internal_decode( unistr, errors='strict'): - if type(unistr) == unicode: - return unistr, len(unistr) - else: - import sys - if sys.maxunicode == 65535: - unicode_bytes = 2 - else: - unicode_bytes = 4 - p = [] - i = 0 - if sys.byteorder == "big": - start = unicode_bytes - 1 - stop = -1 - step = -1 - else: - start = 0 - stop = unicode_bytes - step = 1 - while i < len(unistr): - if len(unistr) - i < unicode_bytes: - msg = 'truncated input' - next, i = unicode_call_errorhandler(errors, 'unicode_internal', msg, - unistr, i, len(unistr)) - p += next - continue - t = 0 - h = 0 - for j in range(start, stop, step): - t += ord(unistr[i+j])<<(h*8) - h += 1 - i += unicode_bytes - try: - p += unichr(t) - except ValueError: - startpos = i - unicode_bytes - endpos = i - msg = "unichr(%s) not in range" % (t,) - next, i = unicode_call_errorhandler(errors, 'unicode_internal', msg, - unistr, startpos, endpos) - p += next - res = u''.join(p) - return res, len(unistr) - # XXX needs error messages when the input is invalid def escape_decode(data, errors='strict'): """None @@ -158,25 +93,3 @@ res = ''.join(res) return res, len(data) -# ---------------------------------------------------------------------- - -def unicode_call_errorhandler(errors, encoding, - reason, input, startinpos, endinpos, decode=True): - - import _codecs - errorHandler = _codecs.lookup_error(errors) - if decode: - exceptionObject = UnicodeDecodeError(encoding, input, startinpos, endinpos, reason) - else: - exceptionObject = UnicodeEncodeError(encoding, input, startinpos, endinpos, reason) - res = errorHandler(exceptionObject) - if isinstance(res, tuple) and len(res) == 2 and isinstance(res[0], unicode) and isinstance(res[1], int): - newpos = res[1] - if (newpos < 0): - newpos = len(input) + newpos - if newpos < 0 or newpos > len(input): - raise IndexError( "position %d from error handler out of bounds" % newpos) - return res[0], newpos - else: - raise TypeError("encoding error handler must return (unicode, int) tuple, not %s" % repr(res)) - Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 14:11:48 2010 @@ -375,6 +375,7 @@ "utf_16_le_encode", "unicode_escape_encode", "raw_unicode_escape_encode", + "unicode_internal_encode", ]: make_encoder_wrapper(encoders) @@ -583,3 +584,25 @@ unicode_name_handler) return space.newtuple([space.wrap(result), space.wrap(consumed)]) + +# ____________________________________________________________ +# Unicode-internal + + at unwrap_spec(ObjSpace, W_Root, str) +def unicode_internal_decode(space, w_string, errors="strict"): + # special case for this codec: unicodes are returned as is + if space.isinstance_w(w_string, space.w_unicode): + return space.newtuple([w_string, space.len(w_string)]) + + string = space.str_w(w_string) + + if len(string) == 0: + return space.newtuple([space.wrap(u''), space.wrap(0)]) + + final = True + state = space.fromcache(CodecState) + result, consumed = runicode.str_decode_unicode_internal( + string, len(string), errors, + final, state.decode_error_handler) + return space.newtuple([space.wrap(result), space.wrap(consumed)]) + Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Tue Jun 29 14:11:48 2010 @@ -1117,6 +1117,90 @@ return result.build() # ____________________________________________________________ +# unicode-internal + +def str_decode_unicode_internal(s, size, errors, final=False, + errorhandler=None): + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + if (size == 0): + return u'', 0 + + if MAXUNICODE < 65536: + unicode_bytes = 2 + else: + unicode_bytes = 4 + if BYTEORDER == "little": + start = 0 + stop = unicode_bytes + step = 1 + else: + start = unicode_bytes - 1 + stop = -1 + step = -1 + + result = UnicodeBuilder(size // unicode_bytes) + pos = 0 + while pos < size: + if pos > size - unicode_bytes: + res, pos = errorhandler(errors, "unicode_internal", + "truncated input", + s, pos, size) + result.append(res) + if pos > size - unicode_bytes: + break + continue + t = 0 + h = 0 + for j in range(start, stop, step): + t += ord(s[pos + j]) << (h*8) + h += 1 + if t > MAXUNICODE: + res, pos = errorhandler(errors, "unicode_internal", + "unichr(%d) not in range" % (t,), + s, pos, pos + unicode_bytes) + result.append(res) + continue + result.append(unichr(t)) + pos += unicode_bytes + return result.build(), pos + +def unicode_encode_unicode_internal(s, size, errors, errorhandler=None): + if (size == 0): + return '' + + if MAXUNICODE < 65536: + unicode_bytes = 2 + else: + unicode_bytes = 4 + + result = StringBuilder(size * unicode_bytes) + pos = 0 + while pos < size: + oc = ord(s[pos]) + if MAXUNICODE < 65536: + if BYTEORDER == "little": + result.append(chr(oc & 0xFF)) + result.append(chr(oc >> 8 & 0xFF)) + else: + result.append(chr(oc >> 8 & 0xFF)) + result.append(chr(oc & 0xFF)) + else: + if BYTEORDER == "little": + result.append(chr(oc & 0xFF)) + result.append(chr(oc >> 8 & 0xFF)) + result.append(chr(oc >> 16 & 0xFF)) + result.append(chr(oc >> 24 & 0xFF)) + else: + result.append(chr(oc >> 24 & 0xFF)) + result.append(chr(oc >> 16 & 0xFF)) + result.append(chr(oc >> 8 & 0xFF)) + result.append(chr(oc & 0xFF)) + pos += 1 + + return result.build() + +# ____________________________________________________________ # MBCS codecs for Windows if sys.platform == 'win32': From afa at codespeak.net Tue Jun 29 14:59:58 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 14:59:58 +0200 (CEST) Subject: [pypy-svn] r75658 - pypy/branch/interplevel-codecs/pypy/module/_codecs Message-ID: <20100629125958.2B3CD282BDE@codespeak.net> Author: afa Date: Tue Jun 29 14:59:57 2010 New Revision: 75658 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Log: last functions: escape_decode and escape_encode. Make them use the string parser and repr. Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Tue Jun 29 14:59:57 2010 @@ -5,9 +5,6 @@ class Module(MixedModule): appleveldefs = { '__doc__' : 'app_codecs.__doc__', - '__name__' : 'app_codecs.__name__', - 'escape_decode' : 'app_codecs.escape_decode', - 'escape_encode' : 'app_codecs.escape_encode', } interpleveldefs = { 'encode': 'interp_codecs.encode', @@ -38,6 +35,8 @@ 'readbuffer_encode': 'interp_codecs.buffer_encode', 'charmap_decode' : 'interp_codecs.charmap_decode', 'charmap_encode' : 'interp_codecs.charmap_encode', + 'escape_encode' : 'interp_codecs.escape_encode', + 'escape_decode' : 'interp_codecs.escape_decode', 'unicode_escape_decode' : 'interp_codecs.unicode_escape_decode', 'unicode_escape_encode' : 'interp_codecs.unicode_escape_encode', 'raw_unicode_escape_decode' : 'interp_codecs.raw_unicode_escape_decode', Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Tue Jun 29 14:59:57 2010 @@ -36,60 +36,3 @@ """ -def escape_encode( obj, errors='strict'): - """None - """ - s = repr(obj) - v = s[1:-1] - return v, len(v) - -# XXX needs error messages when the input is invalid -def escape_decode(data, errors='strict'): - """None - """ - l = len(data) - i = 0 - res = [] - while i < l: - - if data[i] == '\\': - i += 1 - if i >= l: - raise ValueError("Trailing \\ in string") - else: - if data[i] == '\\': - res += '\\' - elif data[i] == 'n': - res += '\n' - elif data[i] == 't': - res += '\t' - elif data[i] == 'r': - res += '\r' - elif data[i] == 'b': - res += '\b' - elif data[i] == '\'': - res += '\'' - elif data[i] == '\"': - res += '\"' - elif data[i] == 'f': - res += '\f' - elif data[i] == 'a': - res += '\a' - elif data[i] == 'v': - res += '\v' - elif '0' <= data[i] <= '9': - # emulate a strange wrap-around behavior of CPython: - # \400 is the same as \000 because 0400 == 256 - octal = data[i:i+3] - res += chr(int(octal, 8) & 0xFF) - i += 2 - elif data[i] == 'x': - hexa = data[i+1:i+3] - res += chr(int(hexa, 16)) - i += 2 - else: - res += data[i] - i += 1 - res = ''.join(res) - return res, len(data) - Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 14:59:57 2010 @@ -396,8 +396,6 @@ make_decoder_wrapper('mbcs_decode') def utf_16_ex_decode(space, data, errors='strict', byteorder=0, w_final=False): - """None - """ final = space.is_true(w_final) state = space.fromcache(CodecState) if byteorder == 0: @@ -606,3 +604,18 @@ final, state.decode_error_handler) return space.newtuple([space.wrap(result), space.wrap(consumed)]) +# ____________________________________________________________ +# support for the "string escape" codec +# This is a bytes-to bytes transformation + + at unwrap_spec(ObjSpace, W_Root, str) +def escape_encode(space, w_string, errors='strict'): + w_repr = space.repr(w_string) + w_result = space.getslice(w_repr, space.wrap(1), space.wrap(-1)) + return space.newtuple([w_result, space.len(w_string)]) + + at unwrap_spec(ObjSpace, str, str) +def escape_decode(space, data, errors='strict'): + from pypy.interpreter.pyparser.parsestring import PyString_DecodeEscape + result = PyString_DecodeEscape(space, data, False, False) + return space.newtuple([space.wrap(result), space.wrap(len(data))]) From afa at codespeak.net Tue Jun 29 15:05:57 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 15:05:57 +0200 (CEST) Subject: [pypy-svn] r75659 - pypy/branch/interplevel-codecs/pypy/module/_codecs Message-ID: <20100629130557.ABAA5282BDE@codespeak.net> Author: afa Date: Tue Jun 29 15:05:56 2010 New Revision: 75659 Removed: pypy/branch/interplevel-codecs/pypy/module/_codecs/app_codecs.py Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Log: Finally remove app_codecs.py Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/__init__.py Tue Jun 29 15:05:56 2010 @@ -3,9 +3,43 @@ from pypy.module._codecs import interp_codecs class Module(MixedModule): - appleveldefs = { - '__doc__' : 'app_codecs.__doc__', - } + """ + _codecs -- Provides access to the codec registry and the builtin + codecs. + + This module should never be imported directly. The standard library + module "codecs" wraps this builtin module for use within Python. + + The codec registry is accessible via: + + register(search_function) -> None + + lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) + + The builtin Unicode codecs use the following interface: + + _encode(Unicode_object[,errors='strict']) -> + (string object, bytes consumed) + + _decode(char_buffer_obj[,errors='strict']) -> + (Unicode object, bytes consumed) + + _encode() interfaces also accept non-Unicode object as + input. The objects are then converted to Unicode using + PyUnicode_FromObject() prior to applying the conversion. + + These s are available: utf_8, unicode_escape, + raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit), + mbcs (on win32). + + +Written by Marc-Andre Lemburg (mal at lemburg.com). + +Copyright (c) Corporation for National Research Initiatives. +""" + + appleveldefs = {} + interpleveldefs = { 'encode': 'interp_codecs.encode', 'decode': 'interp_codecs.decode', From afa at codespeak.net Tue Jun 29 15:47:33 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 15:47:33 +0200 (CEST) Subject: [pypy-svn] r75660 - in pypy/branch/interplevel-codecs/pypy: module/_codecs rlib Message-ID: <20100629134733.A507B282BDE@codespeak.net> Author: afa Date: Tue Jun 29 15:47:32 2010 New Revision: 75660 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: Fix translation, and be sure to have a non-None error handler Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 15:47:32 2010 @@ -617,5 +617,5 @@ @unwrap_spec(ObjSpace, str, str) def escape_decode(space, data, errors='strict'): from pypy.interpreter.pyparser.parsestring import PyString_DecodeEscape - result = PyString_DecodeEscape(space, data, False, False) + result = PyString_DecodeEscape(space, data, False, None) return space.newtuple([space.wrap(result), space.wrap(len(data))]) Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Tue Jun 29 15:47:32 2010 @@ -754,6 +754,9 @@ return unicode_encode_latin_1(s, size, errors, errorhandler=errorhandler) + if errorhandler is None: + errorhandler = raise_unicode_exception_encode + if size == 0: return '' result = StringBuilder(size) From arigo at codespeak.net Tue Jun 29 16:28:46 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 29 Jun 2010 16:28:46 +0200 (CEST) Subject: [pypy-svn] r75661 - pypy/branch/multijit-4/pypy/rlib/rsre/test Message-ID: <20100629142846.7D075282BDE@codespeak.net> Author: arigo Date: Tue Jun 29 16:28:44 2010 New Revision: 75661 Modified: pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py Log: Add a test. Modified: pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py ============================================================================== --- pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py (original) +++ pypy/branch/multijit-4/pypy/rlib/rsre/test/test_search.py Tue Jun 29 16:28:44 2010 @@ -47,3 +47,9 @@ assert groups[i] == (0, 1) else: assert groups[i] == (-1, -1) + + def test_code3(self): + r_code3 = self.get_code(r'xy(?:ab)+c') + state = rsre.SimpleStringState("xyababababcd") + res = state.search(r_code3) + assert res is not None From arigo at codespeak.net Tue Jun 29 16:48:48 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 29 Jun 2010 16:48:48 +0200 (CEST) Subject: [pypy-svn] r75662 - in pypy/trunk/pypy: jit/backend jit/backend/llgraph jit/backend/test jit/backend/x86 jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/test jit/tl jit/tl/spli jit/tl/tinyframe module/__builtin__ module/__builtin__/test Message-ID: <20100629144848.E3ACA282BDE@codespeak.net> Author: arigo Date: Tue Jun 29 16:48:45 2010 New Revision: 75662 Added: pypy/trunk/pypy/jit/metainterp/jitdriver.py - copied unchanged from r75661, pypy/branch/multijit-4/pypy/jit/metainterp/jitdriver.py pypy/trunk/pypy/jit/metainterp/test/test_jitdriver.py - copied unchanged from r75661, pypy/branch/multijit-4/pypy/jit/metainterp/test/test_jitdriver.py Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py pypy/trunk/pypy/jit/backend/model.py pypy/trunk/pypy/jit/backend/test/runner_test.py pypy/trunk/pypy/jit/backend/x86/assembler.py pypy/trunk/pypy/jit/backend/x86/regalloc.py pypy/trunk/pypy/jit/codewriter/assembler.py pypy/trunk/pypy/jit/codewriter/call.py pypy/trunk/pypy/jit/codewriter/codewriter.py pypy/trunk/pypy/jit/codewriter/jitcode.py pypy/trunk/pypy/jit/codewriter/jtransform.py pypy/trunk/pypy/jit/codewriter/test/test_assembler.py pypy/trunk/pypy/jit/codewriter/test/test_call.py pypy/trunk/pypy/jit/codewriter/test/test_codewriter.py pypy/trunk/pypy/jit/codewriter/test/test_flatten.py pypy/trunk/pypy/jit/metainterp/blackhole.py pypy/trunk/pypy/jit/metainterp/compile.py pypy/trunk/pypy/jit/metainterp/history.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/resoperation.py pypy/trunk/pypy/jit/metainterp/resume.py pypy/trunk/pypy/jit/metainterp/test/test_basic.py pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py pypy/trunk/pypy/jit/metainterp/test/test_compile.py pypy/trunk/pypy/jit/metainterp/test/test_list.py pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py pypy/trunk/pypy/jit/metainterp/virtualizable.py pypy/trunk/pypy/jit/metainterp/warmspot.py pypy/trunk/pypy/jit/metainterp/warmstate.py pypy/trunk/pypy/jit/tl/spli/targetspli.py pypy/trunk/pypy/jit/tl/targettlc.py pypy/trunk/pypy/jit/tl/targettlr.py pypy/trunk/pypy/jit/tl/tinyframe/targettinyframe.py pypy/trunk/pypy/module/__builtin__/functional.py pypy/trunk/pypy/module/__builtin__/test/test_functional.py Log: Merge branch/multijit-4, adding support for multiple JITs in the same RPython program. They are declared simply with several JitDriver subclasses. This version should even support arbitrary interactions between the JITs, although not all cases are fully tested. Add as an example a second JitDriver in PyPy's implementation of __builtin__.map(). Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py Tue Jun 29 16:48:45 2010 @@ -832,13 +832,16 @@ raise Exception("Nonsense type %s" % TYPE) failindex = self.cpu._execute_token(loop_token) + jd = loop_token.outermost_jitdriver_sd + assert jd is not None, ("call_assembler(): the loop_token needs " + "to have 'outermost_jitdriver_sd'") + if jd.index_of_virtualizable != -1: + vable = args[jd.index_of_virtualizable] + else: + vable = lltype.nullptr(llmemory.GCREF.TO) + assembler_helper_ptr = jd.assembler_helper_adr.ptr # fish try: - if self.cpu.index_of_virtualizable != -1: - return self.cpu.assembler_helper_ptr(failindex, - args[self.cpu.index_of_virtualizable]) - else: - return self.cpu.assembler_helper_ptr(failindex, - lltype.nullptr(llmemory.GCREF.TO)) + return assembler_helper_ptr(failindex, vable) except LLException, lle: assert _last_exception is None, "exception left behind" _last_exception = lle Modified: pypy/trunk/pypy/jit/backend/model.py ============================================================================== --- pypy/trunk/pypy/jit/backend/model.py (original) +++ pypy/trunk/pypy/jit/backend/model.py Tue Jun 29 16:48:45 2010 @@ -3,10 +3,6 @@ class AbstractCPU(object): supports_floats = False - _got_exception = None - # assembler_helper_ptr - a pointer to helper to call after a direct - # assembler call - portal_calldescr = None done_with_this_frame_void_v = -1 done_with_this_frame_int_v = -1 done_with_this_frame_ref_v = -1 Modified: pypy/trunk/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/trunk/pypy/jit/backend/test/runner_test.py (original) +++ pypy/trunk/pypy/jit/backend/test/runner_test.py Tue Jun 29 16:48:45 2010 @@ -1698,16 +1698,22 @@ assert self.cpu.get_latest_value_int(0) == 10 called.append(failindex) return 4 + 9 - self.cpu.index_of_virtualizable = -1 - self.cpu.assembler_helper_ptr = llhelper(lltype.Ptr(lltype.FuncType - ([lltype.Signed, llmemory.GCREF], lltype.Signed)), assembler_helper) - + + FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF], + lltype.Signed)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + ops = ''' [i0, i1] i2 = int_add(i0, i1) finish(i2)''' loop = parse(ops) looptoken = LoopToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) ARGS = [lltype.Signed, lltype.Signed] RES = lltype.Signed @@ -1739,9 +1745,15 @@ assert self.cpu.get_latest_value_float(0) == 1.2 + 3.2 called.append(failindex) return 13.5 - self.cpu.index_of_virtualizable = -1 - self.cpu.assembler_helper_ptr = llhelper(lltype.Ptr(lltype.FuncType - ([lltype.Signed, llmemory.GCREF], lltype.Float)), assembler_helper) + + FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF], + lltype.Float)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + ARGS = [lltype.Float, lltype.Float] RES = lltype.Float self.cpu.portal_calldescr = self.cpu.calldescrof( @@ -1753,6 +1765,7 @@ finish(f2)''' loop = parse(ops) looptoken = LoopToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) self.cpu.set_future_value_float(0, 1.2) self.cpu.set_future_value_float(1, 2.3) Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Tue Jun 29 16:48:45 2010 @@ -109,7 +109,6 @@ self.malloc_array_func_addr = 0 self.malloc_str_func_addr = 0 self.malloc_unicode_func_addr = 0 - self.assembler_helper_adr = 0 self.fail_boxes_int = values_array(lltype.Signed, failargs_limit) self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit) self.fail_boxes_float = values_array(lltype.Float, failargs_limit) @@ -144,14 +143,6 @@ ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode() self.malloc_unicode_func_addr = rffi.cast(lltype.Signed, ll_new_unicode) - if we_are_translated(): - self.assembler_helper_adr = self.cpu.cast_ptr_to_int( - self.cpu.assembler_helper_ptr) - else: - if getattr(self.cpu, 'assembler_helper_ptr', None): - self.assembler_helper_adr = self.cpu.cast_ptr_to_int( - self.cpu.assembler_helper_ptr) - # done # we generate the loop body in 'mc' # 'mc2' is for guard recovery code @@ -1389,7 +1380,10 @@ je_location = mc.get_relative_pos() # # Path A: use assembler_helper_adr - self._emit_call(rel32(self.assembler_helper_adr), [eax, arglocs[1]], 0, + jd = descr.outermost_jitdriver_sd + assert jd is not None + asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr) + self._emit_call(rel32(asm_helper_adr), [eax, arglocs[1]], 0, tmp=ecx, force_mc=True, mc=mc) if isinstance(result_loc, MODRM64): mc.FSTP(result_loc) @@ -1403,9 +1397,9 @@ mc.overwrite(je_location - 1, [chr(offset)]) # # Reset the vable token --- XXX really too much special logic here:-( - if self.cpu.index_of_virtualizable >= 0: + if jd.index_of_virtualizable >= 0: from pypy.jit.backend.llsupport.descr import BaseFieldDescr - fielddescr = self.cpu.vable_token_descr + fielddescr = jd.vable_token_descr assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset mc.MOV(eax, arglocs[1]) Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Tue Jun 29 16:48:45 2010 @@ -636,10 +636,14 @@ self._consider_call(op, guard_op) def consider_call_assembler(self, op, guard_op): - descr = op.descr portal_calldescr = self.assembler.cpu.portal_calldescr size = portal_calldescr.get_result_size(self.translate_support_code) - vable_index = self.assembler.cpu.index_of_virtualizable + # + descr = op.descr + assert isinstance(descr, LoopToken) + jd = descr.outermost_jitdriver_sd + assert jd is not None + vable_index = jd.index_of_virtualizable if vable_index >= 0: self.rm._sync_var(op.args[vable_index]) vable = self.fm.loc(op.args[vable_index], 1) Modified: pypy/trunk/pypy/jit/codewriter/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/assembler.py (original) +++ pypy/trunk/pypy/jit/codewriter/assembler.py Tue Jun 29 16:48:45 2010 @@ -60,37 +60,38 @@ self.code.append(chr(reg.index)) def emit_const(self, const, kind, allow_short=False): - if const not in self.constants_dict: - value = const.value - TYPE = lltype.typeOf(value) - if kind == 'int': - if isinstance(TYPE, lltype.Ptr): - assert TYPE.TO._gckind == 'raw' - self.see_raw_object(value) - value = llmemory.cast_ptr_to_adr(value) - TYPE = llmemory.Address - if TYPE == llmemory.Address: - value = heaptracker.adr2int(value) - elif not isinstance(value, ComputedIntSymbolic): - value = lltype.cast_primitive(lltype.Signed, value) - if allow_short and -128 <= value <= 127: - # emit the constant as a small integer - self.code.append(chr(value & 0xFF)) - return True - constants = self.constants_i - elif kind == 'ref': - value = lltype.cast_opaque_ptr(llmemory.GCREF, value) - constants = self.constants_r - elif kind == 'float': - assert TYPE == lltype.Float - constants = self.constants_f - else: - raise NotImplementedError(const) + value = const.value + TYPE = lltype.typeOf(value) + if kind == 'int': + if isinstance(TYPE, lltype.Ptr): + assert TYPE.TO._gckind == 'raw' + self.see_raw_object(value) + value = llmemory.cast_ptr_to_adr(value) + TYPE = llmemory.Address + if TYPE == llmemory.Address: + value = heaptracker.adr2int(value) + elif not isinstance(value, ComputedIntSymbolic): + value = lltype.cast_primitive(lltype.Signed, value) + if allow_short and -128 <= value <= 127: + # emit the constant as a small integer + self.code.append(chr(value & 0xFF)) + return True + constants = self.constants_i + elif kind == 'ref': + value = lltype.cast_opaque_ptr(llmemory.GCREF, value) + constants = self.constants_r + elif kind == 'float': + assert TYPE == lltype.Float + constants = self.constants_f + else: + raise NotImplementedError(const) + key = (kind, Constant(value)) + if key not in self.constants_dict: constants.append(value) - self.constants_dict[const] = 256 - len(constants) + self.constants_dict[key] = 256 - len(constants) # emit the constant normally, as one byte that is an index in the # list of constants - self.code.append(chr(self.constants_dict[const])) + self.code.append(chr(self.constants_dict[key])) return False def write_insn(self, insn): Modified: pypy/trunk/pypy/jit/codewriter/call.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/call.py (original) +++ pypy/trunk/pypy/jit/codewriter/call.py Tue Jun 29 16:48:45 2010 @@ -16,21 +16,22 @@ class CallControl(object): virtualref_info = None # optionally set from outside - virtualizable_info = None # optionally set from outside - portal_runner_ptr = None # optionally set from outside - def __init__(self, cpu=None, portal_graph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): + assert isinstance(jitdrivers_sd, list) # debugging self.cpu = cpu - self.portal_graph = portal_graph + self.jitdrivers_sd = jitdrivers_sd self.jitcodes = {} # map {graph: jitcode} self.unfinished_graphs = [] # list of graphs with pending jitcodes - self.jitdriver = None if hasattr(cpu, 'rtyper'): # for tests self.rtyper = cpu.rtyper translator = self.rtyper.annotator.translator self.raise_analyzer = RaiseAnalyzer(translator) self.readwrite_analyzer = ReadWriteAnalyzer(translator) self.virtualizable_analyzer = VirtualizableAnalyzer(translator) + # + for index, jd in enumerate(jitdrivers_sd): + jd.index = index def find_all_graphs(self, policy): try: @@ -41,8 +42,8 @@ def is_candidate(graph): return policy.look_inside_graph(graph) - assert self.portal_graph is not None - todo = [self.portal_graph] + assert len(self.jitdrivers_sd) > 0 + todo = [jd.portal_graph for jd in self.jitdrivers_sd] if hasattr(self, 'rtyper'): for oopspec_name, ll_args, ll_res in support.inline_calls_to: c_func, _ = support.builtin_func_for_spec(self.rtyper, @@ -122,7 +123,7 @@ def guess_call_kind(self, op, is_candidate=None): if op.opname == 'direct_call': funcptr = op.args[0].value - if funcptr is self.portal_runner_ptr: + if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None: return 'recursive' funcobj = get_funcobj(funcptr) if getattr(funcobj, 'graph', None) is None: @@ -143,6 +144,11 @@ # used only after find_all_graphs() return graph in self.candidate_graphs + def grab_initial_jitcodes(self): + for jd in self.jitdrivers_sd: + jd.mainjitcode = self.get_jitcode(jd.portal_graph) + jd.mainjitcode.is_portal = True + def enum_pending_graphs(self): while self.unfinished_graphs: graph = self.unfinished_graphs.pop() @@ -241,12 +247,32 @@ return (effectinfo is None or effectinfo.extraeffect >= EffectInfo.EF_CAN_RAISE) - def found_jitdriver(self, jitdriver): - if self.jitdriver is None: - self.jitdriver = jitdriver - else: - assert self.jitdriver is jitdriver + def jitdriver_sd_from_portal_graph(self, graph): + for jd in self.jitdrivers_sd: + if jd.portal_graph is graph: + return jd + return None - def getjitdriver(self): - assert self.jitdriver is not None, "order dependency issue?" - return self.jitdriver + def jitdriver_sd_from_portal_runner_ptr(self, funcptr): + for jd in self.jitdrivers_sd: + if funcptr is jd.portal_runner_ptr: + return jd + return None + + def jitdriver_sd_from_jitdriver(self, jitdriver): + for jd in self.jitdrivers_sd: + if jd.jitdriver is jitdriver: + return jd + return None + + def get_vinfo(self, VTYPEPTR): + seen = set() + for jd in self.jitdrivers_sd: + if jd.virtualizable_info is not None: + if jd.virtualizable_info.is_vtypeptr(VTYPEPTR): + seen.add(jd.virtualizable_info) + if seen: + assert len(seen) == 1 + return seen.pop() + else: + return None Modified: pypy/trunk/pypy/jit/codewriter/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/codewriter.py (original) +++ pypy/trunk/pypy/jit/codewriter/codewriter.py Tue Jun 29 16:48:45 2010 @@ -14,29 +14,30 @@ class CodeWriter(object): callcontrol = None # for tests - def __init__(self, cpu=None, maingraph=None): + def __init__(self, cpu=None, jitdrivers_sd=[]): self.cpu = cpu self.assembler = Assembler() - self.portal_graph = maingraph - self.callcontrol = CallControl(cpu, maingraph) + self.callcontrol = CallControl(cpu, jitdrivers_sd) + self._seen_files = set() def transform_func_to_jitcode(self, func, values, type_system='lltype'): """For testing.""" rtyper = support.annotate(func, values, type_system=type_system) graph = rtyper.annotator.translator.graphs[0] jitcode = JitCode("test") - self.transform_graph_to_jitcode(graph, jitcode, True, True) + self.transform_graph_to_jitcode(graph, jitcode, True) return jitcode - def transform_graph_to_jitcode(self, graph, jitcode, portal, verbose): + def transform_graph_to_jitcode(self, graph, jitcode, verbose): """Transform a graph into a JitCode containing the same bytecode in a different format. """ + portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph) graph = copygraph(graph, shallowvars=True) # # step 1: mangle the graph so that it contains the final instructions # that we want in the JitCode, but still as a control flow graph - transform_graph(graph, self.cpu, self.callcontrol, portal) + transform_graph(graph, self.cpu, self.callcontrol, portal_jd) # # step 2: perform register allocation on it regallocs = {} @@ -59,16 +60,14 @@ self.assembler.assemble(ssarepr, jitcode) # # print the resulting assembler - self.print_ssa_repr(ssarepr, portal, verbose) + self.print_ssa_repr(ssarepr, portal_jd, verbose) def make_jitcodes(self, verbose=False): log.info("making JitCodes...") - maingraph = self.portal_graph - self.mainjitcode = self.callcontrol.get_jitcode(maingraph) + self.callcontrol.grab_initial_jitcodes() count = 0 for graph, jitcode in self.callcontrol.enum_pending_graphs(): - self.transform_graph_to_jitcode(graph, jitcode, - graph is maingraph, verbose) + self.transform_graph_to_jitcode(graph, jitcode, verbose) count += 1 if not count % 500: log.info("Produced %d jitcodes" % count) @@ -76,33 +75,35 @@ log.info("there are %d JitCode instances." % count) def setup_vrefinfo(self, vrefinfo): + # must be called at most once + assert self.callcontrol.virtualref_info is None self.callcontrol.virtualref_info = vrefinfo - def setup_virtualizable_info(self, vinfo): - self.callcontrol.virtualizable_info = vinfo - - def setup_portal_runner_ptr(self, portal_runner_ptr): - self.callcontrol.portal_runner_ptr = portal_runner_ptr + def setup_jitdriver(self, jitdriver_sd): + # Must be called once per jitdriver. Usually jitdriver_sd is an + # instance of pypy.jit.metainterp.jitdriver.JitDriverStaticData. + self.callcontrol.jitdrivers_sd.append(jitdriver_sd) def find_all_graphs(self, policy): return self.callcontrol.find_all_graphs(policy) - def print_ssa_repr(self, ssarepr, portal, verbose): + def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose): if verbose: print '%s:' % (ssarepr.name,) print format_assembler(ssarepr) else: dir = udir.ensure("jitcodes", dir=1) - if portal: - name = "00_portal_runner" + if portal_jitdriver: + name = "%02d_portal_runner" % (portal_jitdriver.index,) elif ssarepr.name and ssarepr.name != '?': name = ssarepr.name else: name = 'unnamed' % id(ssarepr) i = 1 extra = '' - while dir.join(name+extra).check(exists=1): + while name+extra in self._seen_files: i += 1 extra = '.%d' % i + self._seen_files.add(name+extra) dir.join(name+extra).write(format_assembler(ssarepr)) log.dot() Modified: pypy/trunk/pypy/jit/codewriter/jitcode.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/jitcode.py (original) +++ pypy/trunk/pypy/jit/codewriter/jitcode.py Tue Jun 29 16:48:45 2010 @@ -13,6 +13,7 @@ self.name = name self.fnaddr = fnaddr self.calldescr = calldescr + self.is_portal = False self._called_from = called_from # debugging self._ssarepr = None # debugging @@ -24,11 +25,11 @@ self.constants_i = constants_i or self._empty_i self.constants_r = constants_r or self._empty_r self.constants_f = constants_f or self._empty_f - # encode the three num_regs into a single integer + # encode the three num_regs into a single char each assert num_regs_i < 256 and num_regs_r < 256 and num_regs_f < 256 - self.num_regs_encoded = ((num_regs_i << 16) | - (num_regs_f << 8) | - (num_regs_r << 0)) + self.c_num_regs_i = chr(num_regs_i) + self.c_num_regs_r = chr(num_regs_r) + self.c_num_regs_f = chr(num_regs_f) self.liveness = make_liveness_cache(liveness) self._startpoints = startpoints # debugging self._alllabels = alllabels # debugging @@ -37,13 +38,13 @@ return heaptracker.adr2int(self.fnaddr) def num_regs_i(self): - return self.num_regs_encoded >> 16 - - def num_regs_f(self): - return (self.num_regs_encoded >> 8) & 0xFF + return ord(self.c_num_regs_i) def num_regs_r(self): - return self.num_regs_encoded & 0xFF + return ord(self.c_num_regs_r) + + def num_regs_f(self): + return ord(self.c_num_regs_f) def has_liveness_info(self, pc): return pc in self.liveness Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/jtransform.py (original) +++ pypy/trunk/pypy/jit/codewriter/jtransform.py Tue Jun 29 16:48:45 2010 @@ -13,23 +13,23 @@ from pypy.translator.simplify import get_funcobj -def transform_graph(graph, cpu=None, callcontrol=None, portal=True): +def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None): """Transform a control flow graph to make it suitable for being flattened in a JitCode. """ - t = Transformer(cpu, callcontrol) - t.transform(graph, portal) + t = Transformer(cpu, callcontrol, portal_jd) + t.transform(graph) class Transformer(object): - def __init__(self, cpu=None, callcontrol=None): + def __init__(self, cpu=None, callcontrol=None, portal_jd=None): self.cpu = cpu self.callcontrol = callcontrol + self.portal_jd = portal_jd # non-None only for the portal graph(s) - def transform(self, graph, portal): + def transform(self, graph): self.graph = graph - self.portal = portal for block in list(graph.iterblocks()): self.optimize_block(block) @@ -325,10 +325,13 @@ return op1 def handle_recursive_call(self, op): - ops = self.promote_greens(op.args[1:]) - targetgraph = self.callcontrol.portal_graph - num_green_args = len(self.callcontrol.getjitdriver().greens) - args = (self.make_three_lists(op.args[1:1+num_green_args]) + + jitdriver_sd = self.callcontrol.jitdriver_sd_from_portal_runner_ptr( + op.args[0].value) + assert jitdriver_sd is not None + ops = self.promote_greens(op.args[1:], jitdriver_sd.jitdriver) + num_green_args = len(jitdriver_sd.jitdriver.greens) + args = ([Constant(jitdriver_sd.index, lltype.Signed)] + + self.make_three_lists(op.args[1:1+num_green_args]) + self.make_three_lists(op.args[1+num_green_args:])) kind = getkind(op.result.concretetype)[0] op0 = SpaceOperation('recursive_call_%s' % kind, args, op.result) @@ -483,14 +486,14 @@ # check for virtualizable try: if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('getfield_vable_%s' % kind, [v_inst, descr], op.result)] - except VirtualizableArrayField: + except VirtualizableArrayField, e: # xxx hack hack hack - vinfo = self.callcontrol.virtualizable_info + vinfo = e.args[1] arrayindex = vinfo.array_field_counter[op.args[1].value] arrayfielddescr = vinfo.array_field_descrs[arrayindex] arraydescr = vinfo.array_descrs[arrayindex] @@ -527,7 +530,7 @@ return # check for virtualizable if self.is_virtualizable_getset(op): - descr = self.get_virtualizable_field_descr(op.args[1].value) + descr = self.get_virtualizable_field_descr(op) kind = getkind(RESULT)[0] return [SpaceOperation('-live-', [], None), SpaceOperation('setfield_vable_%s' % kind, @@ -544,21 +547,23 @@ return (op.args[1].value == 'typeptr' and op.args[0].concretetype.TO._hints.get('typeptr')) + def get_vinfo(self, v_virtualizable): + if self.callcontrol is None: # for tests + return None + return self.callcontrol.get_vinfo(v_virtualizable.concretetype) + def is_virtualizable_getset(self, op): # every access of an object of exactly the type VTYPEPTR is # likely to be a virtualizable access, but we still have to # check it in pyjitpl.py. - try: - vinfo = self.callcontrol.virtualizable_info - except AttributeError: - return False - if vinfo is None or not vinfo.is_vtypeptr(op.args[0].concretetype): + vinfo = self.get_vinfo(op.args[0]) + if vinfo is None: return False res = False if op.args[1].value in vinfo.static_field_to_extra_box: res = True if op.args[1].value in vinfo.array_fields: - res = VirtualizableArrayField(self.graph) + res = VirtualizableArrayField(self.graph, vinfo) if res: flags = self.vable_flags[op.args[0]] @@ -568,8 +573,9 @@ raise res return res - def get_virtualizable_field_descr(self, fieldname): - vinfo = self.callcontrol.virtualizable_info + def get_virtualizable_field_descr(self, op): + fieldname = op.args[1].value + vinfo = self.get_vinfo(op.args[0]) index = vinfo.static_field_to_extra_box[fieldname] return vinfo.static_field_descrs[index] @@ -750,9 +756,10 @@ return Constant(value, lltype.Bool) return op - def promote_greens(self, args): + def promote_greens(self, args, jitdriver): ops = [] - num_green_args = len(self.callcontrol.getjitdriver().greens) + num_green_args = len(jitdriver.greens) + assert len(args) == num_green_args + len(jitdriver.reds) for v in args[:num_green_args]: if isinstance(v, Variable) and v.concretetype is not lltype.Void: kind = getkind(v.concretetype) @@ -762,21 +769,28 @@ return ops def rewrite_op_jit_marker(self, op): - self.callcontrol.found_jitdriver(op.args[1].value) key = op.args[0].value - return getattr(self, 'handle_jit_marker__%s' % key)(op) + jitdriver = op.args[1].value + return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver) - def handle_jit_marker__jit_merge_point(self, op): - assert self.portal, "jit_merge_point in non-main graph!" - ops = self.promote_greens(op.args[2:]) - num_green_args = len(self.callcontrol.getjitdriver().greens) - args = (self.make_three_lists(op.args[2:2+num_green_args]) + + def handle_jit_marker__jit_merge_point(self, op, jitdriver): + assert self.portal_jd is not None, ( + "'jit_merge_point' in non-portal graph!") + assert jitdriver is self.portal_jd.jitdriver, ( + "general mix-up of jitdrivers?") + ops = self.promote_greens(op.args[2:], jitdriver) + num_green_args = len(jitdriver.greens) + args = ([Constant(self.portal_jd.index, lltype.Signed)] + + self.make_three_lists(op.args[2:2+num_green_args]) + self.make_three_lists(op.args[2+num_green_args:])) op1 = SpaceOperation('jit_merge_point', args, None) return ops + [op1] - def handle_jit_marker__can_enter_jit(self, op): - return SpaceOperation('can_enter_jit', [], None) + def handle_jit_marker__can_enter_jit(self, op, jitdriver): + jd = self.callcontrol.jitdriver_sd_from_jitdriver(jitdriver) + assert jd is not None + c_index = Constant(jd.index, lltype.Signed) + return SpaceOperation('can_enter_jit', [c_index], None) def rewrite_op_debug_assert(self, op): log.WARNING("found debug_assert in %r; should have be removed" % @@ -974,9 +988,8 @@ def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables - vinfo = self.callcontrol.virtualizable_info + vinfo = self.get_vinfo(op.args[0]) assert vinfo is not None - assert vinfo.is_vtypeptr(op.args[0].concretetype) self.vable_flags[op.args[0]] = op.args[2].value return [] Modified: pypy/trunk/pypy/jit/codewriter/test/test_assembler.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_assembler.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_assembler.py Tue Jun 29 16:48:45 2010 @@ -127,6 +127,25 @@ assert assembler.insns == {'foobar/IR': 0} assert jitcode.constants_i == [42] +def test_assemble_list_semibug(): + # the semibug is that after forcing 42 into the dict of constants, + # it would be reused for all future 42's, even ones that can be + # encoded directly. + ssarepr = SSARepr("test") + ssarepr.insns = [ + ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])), + ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])), + ('baz', Constant(42, lltype.Signed)), + ] + assembler = Assembler() + jitcode = assembler.assemble(ssarepr) + assert jitcode.code == ("\x00\x01\xFF" + "\x00\x01\xFF" + "\x01\x2A") + assert assembler.insns == {'foobar/I': 0, + 'baz/c': 1} + assert jitcode.constants_i == [42] + def test_assemble_descr(): class FooDescr(AbstractDescr): pass Modified: pypy/trunk/pypy/jit/codewriter/test/test_call.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_call.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_call.py Tue Jun 29 16:48:45 2010 @@ -52,13 +52,19 @@ # ____________________________________________________________ +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + def test_find_all_graphs(): def g(x): return x + 2 def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) res = cc.find_all_graphs(FakePolicy()) funcs = set([graph.func for graph in res]) assert funcs == set([f, g]) @@ -69,7 +75,8 @@ def f(x): return g(x) + 1 rtyper = support.annotate(f, [7]) - cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0]) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cc = CallControl(jitdrivers_sd=[jitdriver_sd]) class CustomFakePolicy: def look_inside_graph(self, graph): assert graph.name == 'g' @@ -83,10 +90,11 @@ def test_guess_call_kind_and_calls_from_graphs(): class portal_runner_obj: graph = object() + class FakeJitDriverSD: + portal_runner_ptr = portal_runner_obj g = object() g1 = object() - cc = CallControl() - cc.portal_runner_ptr = portal_runner_obj + cc = CallControl(jitdrivers_sd=[FakeJitDriverSD()]) cc.candidate_graphs = [g, g1] op = SpaceOperation('direct_call', [Constant(portal_runner_obj)], Modified: pypy/trunk/pypy/jit/codewriter/test/test_codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_codewriter.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_codewriter.py Tue Jun 29 16:48:45 2010 @@ -35,6 +35,12 @@ def look_inside_graph(self, graph): return graph.name != 'dont_look' +class FakeJitDriverSD: + def __init__(self, portal_graph): + self.portal_graph = portal_graph + self.portal_runner_ptr = "???" + self.virtualizable_info = None + def test_loop(): def f(a, b): @@ -70,11 +76,11 @@ def fff(a, b): return ggg(b) - ggg(a) rtyper = support.annotate(fff, [35, 42]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) - jitcode = cw.mainjitcode + jitcode = jitdriver_sd.mainjitcode print jitcode.dump() [jitcode2] = cw.assembler.descrs print jitcode2.dump() @@ -100,7 +106,7 @@ blackholeinterp.setarg_i(0, 6) blackholeinterp.setarg_i(1, 100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 100+6+5+4+3 + assert blackholeinterp.get_tmpreg_i() == 100+6+5+4+3 def test_instantiate(): class A1: id = 651 @@ -117,7 +123,7 @@ return x().id + y().id + dont_look(n) rtyper = support.annotate(f, [35]) maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # @@ -144,10 +150,10 @@ def f(n): return abs(n) rtyper = support.annotate(f, [35]) - maingraph = rtyper.annotator.translator.graphs[0] - cw = CodeWriter(FakeCPU(rtyper), maingraph) + jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0]) + cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd]) cw.find_all_graphs(FakePolicy()) cw.make_jitcodes(verbose=True) # - s = cw.mainjitcode.dump() + s = jitdriver_sd.mainjitcode.dump() assert "inline_call_ir_i " in s Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py ============================================================================== --- pypy/trunk/pypy/jit/codewriter/test/test_flatten.py (original) +++ pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Tue Jun 29 16:48:45 2010 @@ -68,11 +68,8 @@ return FakeDescr() def calldescr_canraise(self, calldescr): return calldescr is not self._descr_cannot_raise - def found_jitdriver(self, jitdriver): - assert isinstance(jitdriver, JitDriver) - self.jitdriver = jitdriver - def getjitdriver(self): - return self.jitdriver + def get_vinfo(self, VTYPEPTR): + return None class FakeCallControlWithVRefInfo: class virtualref_info: @@ -118,13 +115,13 @@ return self.rtyper.annotator.translator.graphs def encoding_test(self, func, args, expected, - transform=False, liveness=False, cc=None): + transform=False, liveness=False, cc=None, jd=None): graphs = self.make_graphs(func, args) #graphs[0].show() if transform: from pypy.jit.codewriter.jtransform import transform_graph cc = cc or FakeCallControl() - transform_graph(graphs[0], FakeCPU(self.rtyper), cc) + transform_graph(graphs[0], FakeCPU(self.rtyper), cc, jd) ssarepr = flatten_graph(graphs[0], fake_regallocs(), _include_all_exc_links=not transform) if liveness: @@ -584,13 +581,21 @@ def f(x, y): myjitdriver.jit_merge_point(x=x, y=y) myjitdriver.can_enter_jit(x=y, y=x) + class FakeJitDriverSD: + jitdriver = myjitdriver + index = 27 + jd = FakeJitDriverSD() + class MyFakeCallControl(FakeCallControl): + def jitdriver_sd_from_jitdriver(self, jitdriver): + assert jitdriver == myjitdriver + return jd self.encoding_test(f, [4, 5], """ -live- %i0, %i1 int_guard_value %i0 - jit_merge_point I[%i0], R[], F[], I[%i1], R[], F[] - can_enter_jit + jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[] + can_enter_jit $27 void_return - """, transform=True, liveness=True) + """, transform=True, liveness=True, cc=MyFakeCallControl(), jd=jd) def test_keepalive(self): S = lltype.GcStruct('S') Modified: pypy/trunk/pypy/jit/metainterp/blackhole.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/blackhole.py (original) +++ pypy/trunk/pypy/jit/metainterp/blackhole.py Tue Jun 29 16:48:45 2010 @@ -315,27 +315,12 @@ def get_tmpreg_f(self): return self.tmpreg_f - def final_result_i(self): - assert self._return_type == 'i' - return self.get_tmpreg_i() - - def final_result_r(self): - assert self._return_type == 'r' - return self.get_tmpreg_r() - - def final_result_f(self): - assert self._return_type == 'f' - return self.get_tmpreg_f() - - def final_result_v(self): - assert self._return_type == 'v' - def _final_result_anytype(self): "NOT_RPYTHON" - if self._return_type == 'i': return self.final_result_i() - if self._return_type == 'r': return self.final_result_r() - if self._return_type == 'f': return self.final_result_f() - if self._return_type == 'v': return self.final_result_v() + if self._return_type == 'i': return self.get_tmpreg_i() + if self._return_type == 'r': return self.get_tmpreg_r() + if self._return_type == 'f': return self.get_tmpreg_f() + if self._return_type == 'v': return None raise ValueError(self._return_type) def cleanup_registers(self): @@ -774,12 +759,12 @@ # ---------- # the main hints and recursive calls - @arguments() - def bhimpl_can_enter_jit(): + @arguments("i") + def bhimpl_can_enter_jit(jdindex): pass - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_jit_merge_point(self, *args): + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_jit_merge_point(self, jdindex, *args): if self.nextblackholeinterp is None: # we are the last level CRN = self.builder.metainterp_sd.ContinueRunningNormally raise CRN(*args) @@ -793,55 +778,55 @@ # call the interpreter main loop from here, and just return its # result. sd = self.builder.metainterp_sd - if sd.result_type == 'void': - self.bhimpl_recursive_call_v(*args) + result_type = sd.jitdrivers_sd[jdindex].result_type + if result_type == 'v': + self.bhimpl_recursive_call_v(jdindex, *args) self.bhimpl_void_return() - elif sd.result_type == 'int': - x = self.bhimpl_recursive_call_i(*args) + elif result_type == 'i': + x = self.bhimpl_recursive_call_i(jdindex, *args) self.bhimpl_int_return(x) - elif sd.result_type == 'ref': - x = self.bhimpl_recursive_call_r(*args) + elif result_type == 'r': + x = self.bhimpl_recursive_call_r(jdindex, *args) self.bhimpl_ref_return(x) - elif sd.result_type == 'float': - x = self.bhimpl_recursive_call_f(*args) + elif result_type == 'f': + x = self.bhimpl_recursive_call_f(jdindex, *args) self.bhimpl_float_return(x) assert False - def get_portal_runner(self): - metainterp_sd = self.builder.metainterp_sd - fnptr = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) - fnptr = heaptracker.adr2int(fnptr) - calldescr = metainterp_sd.portal_code.calldescr + def get_portal_runner(self, jdindex): + jitdriver_sd = self.builder.metainterp_sd.jitdrivers_sd[jdindex] + fnptr = heaptracker.adr2int(jitdriver_sd.portal_runner_adr) + calldescr = jitdriver_sd.mainjitcode.calldescr return fnptr, calldescr - @arguments("self", "I", "R", "F", "I", "R", "F", returns="i") - def bhimpl_recursive_call_i(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="i") + def bhimpl_recursive_call_i(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_i(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="r") - def bhimpl_recursive_call_r(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="r") + def bhimpl_recursive_call_r(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_r(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F", returns="f") - def bhimpl_recursive_call_f(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F", returns="f") + def bhimpl_recursive_call_f(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_f(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, greens_f + reds_f) - @arguments("self", "I", "R", "F", "I", "R", "F") - def bhimpl_recursive_call_v(self, greens_i, greens_r, greens_f, - reds_i, reds_r, reds_f): - fnptr, calldescr = self.get_portal_runner() + @arguments("self", "i", "I", "R", "F", "I", "R", "F") + def bhimpl_recursive_call_v(self, jdindex, greens_i, greens_r, greens_f, + reds_i, reds_r, reds_f): + fnptr, calldescr = self.get_portal_runner(jdindex) return self.cpu.bh_call_v(fnptr, calldescr, greens_i + reds_i, greens_r + reds_r, @@ -1178,11 +1163,11 @@ self._done_with_this_frame() kind = self._return_type if kind == 'i': - caller._setup_return_value_i(self.final_result_i()) + caller._setup_return_value_i(self.get_tmpreg_i()) elif kind == 'r': - caller._setup_return_value_r(self.final_result_r()) + caller._setup_return_value_r(self.get_tmpreg_r()) elif kind == 'f': - caller._setup_return_value_f(self.final_result_f()) + caller._setup_return_value_f(self.get_tmpreg_f()) else: assert kind == 'v' return lltype.nullptr(rclass.OBJECTPTR.TO) @@ -1248,15 +1233,15 @@ # rare case: we only get there if the blackhole interps all returned # normally (in general we get a ContinueRunningNormally exception). sd = self.builder.metainterp_sd - if sd.result_type == 'void': - self.final_result_v() + kind = self._return_type + if kind == 'v': raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': - raise sd.DoneWithThisFrameInt(self.final_result_i()) - elif sd.result_type == 'ref': - raise sd.DoneWithThisFrameRef(self.cpu, self.final_result_r()) - elif sd.result_type == 'float': - raise sd.DoneWithThisFrameFloat(self.final_result_f()) + elif kind == 'i': + raise sd.DoneWithThisFrameInt(self.get_tmpreg_i()) + elif kind == 'r': + raise sd.DoneWithThisFrameRef(self.cpu, self.get_tmpreg_r()) + elif kind == 'f': + raise sd.DoneWithThisFrameFloat(self.get_tmpreg_f()) else: assert False @@ -1290,12 +1275,14 @@ blackholeinterp.builder.release_interp(blackholeinterp) blackholeinterp = blackholeinterp.nextblackholeinterp -def resume_in_blackhole(metainterp_sd, resumedescr, all_virtuals=None): +def resume_in_blackhole(metainterp_sd, jitdriver_sd, resumedescr, + all_virtuals=None): from pypy.jit.metainterp.resume import blackhole_from_resumedata debug_start('jit-blackhole') metainterp_sd.profiler.start_blackhole() blackholeinterp = blackhole_from_resumedata( metainterp_sd.blackholeinterpbuilder, + jitdriver_sd, resumedescr, all_virtuals) current_exc = blackholeinterp._prepare_resume_from_failure( Modified: pypy/trunk/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/compile.py (original) +++ pypy/trunk/pypy/jit/metainterp/compile.py Tue Jun 29 16:48:45 2010 @@ -39,9 +39,10 @@ name = metainterp.staticdata.stats.name_for_new_loop() return TreeLoop(name) -def make_loop_token(nb_args): +def make_loop_token(nb_args, jitdriver_sd): loop_token = LoopToken() loop_token.specnodes = [prebuiltNotSpecNode] * nb_args + loop_token.outermost_jitdriver_sd = jitdriver_sd return loop_token # ____________________________________________________________ @@ -63,11 +64,12 @@ # make a copy, because optimize_loop can mutate the ops and descrs loop.operations = [op.clone() for op in ops] metainterp_sd = metainterp.staticdata - loop_token = make_loop_token(len(loop.inputargs)) + jitdriver_sd = metainterp.jitdriver_sd + loop_token = make_loop_token(len(loop.inputargs), jitdriver_sd) loop.token = loop_token loop.operations[-1].descr = loop_token # patch the target of the JUMP try: - old_loop_token = metainterp_sd.state.optimize_loop( + old_loop_token = jitdriver_sd.warmstate.optimize_loop( metainterp_sd, old_loop_tokens, loop) except InvalidLoop: return None @@ -141,32 +143,32 @@ pass class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'void' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.VOID raise metainterp_sd.DoneWithThisFrameVoid() class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'int' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.INT result = metainterp_sd.cpu.get_latest_value_int(0) raise metainterp_sd.DoneWithThisFrameInt(result) class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'ref' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.REF cpu = metainterp_sd.cpu result = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) raise metainterp_sd.DoneWithThisFrameRef(cpu, result) class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): - assert metainterp_sd.result_type == 'float' + def handle_fail(self, metainterp_sd, jitdriver_sd): + assert jitdriver_sd.result_type == history.FLOAT result = metainterp_sd.cpu.get_latest_value_float(0) raise metainterp_sd.DoneWithThisFrameFloat(result) class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr): - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): cpu = metainterp_sd.cpu value = cpu.get_latest_value_ref(0) cpu.clear_latest_values(1) @@ -210,8 +212,6 @@ class ResumeDescr(AbstractFailDescr): def __init__(self, original_greenkey): self.original_greenkey = original_greenkey - def _clone_if_mutable(self): - raise NotImplementedError class ResumeGuardDescr(ResumeDescr): _counter = 0 # if < 0, there is one counter per value; @@ -258,22 +258,27 @@ # a negative value self._counter = cnt | i - def handle_fail(self, metainterp_sd): - if self.must_compile(metainterp_sd): - return self._trace_and_compile_from_bridge(metainterp_sd) + def handle_fail(self, metainterp_sd, jitdriver_sd): + if self.must_compile(metainterp_sd, jitdriver_sd): + return self._trace_and_compile_from_bridge(metainterp_sd, + jitdriver_sd) else: from pypy.jit.metainterp.blackhole import resume_in_blackhole - resume_in_blackhole(metainterp_sd, self) + resume_in_blackhole(metainterp_sd, jitdriver_sd, self) assert 0, "unreachable" - def _trace_and_compile_from_bridge(self, metainterp_sd): + def _trace_and_compile_from_bridge(self, metainterp_sd, jitdriver_sd): + # 'jitdriver_sd' corresponds to the outermost one, i.e. the one + # of the jit_merge_point where we started the loop, even if the + # loop itself may contain temporarily recursion into other + # jitdrivers. from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) return metainterp.handle_guard_failure(self) _trace_and_compile_from_bridge._dont_inline_ = True - def must_compile(self, metainterp_sd): - trace_eagerness = metainterp_sd.state.trace_eagerness + def must_compile(self, metainterp_sd, jitdriver_sd): + trace_eagerness = jitdriver_sd.warmstate.trace_eagerness if self._counter >= 0: self._counter += 1 return self._counter >= trace_eagerness @@ -320,8 +325,7 @@ send_bridge_to_backend(metainterp.staticdata, self, inputargs, new_loop.operations) - def _clone_if_mutable(self): - res = self.__class__(self.metainterp_sd, self.original_greenkey) + def copy_all_attrbutes_into(self, res): # XXX a bit ugly to have to list them all here res.rd_snapshot = self.rd_snapshot res.rd_frame_info_list = self.rd_frame_info_list @@ -329,11 +333,19 @@ res.rd_consts = self.rd_consts res.rd_virtuals = self.rd_virtuals res.rd_pendingfields = self.rd_pendingfields + + def _clone_if_mutable(self): + res = ResumeGuardDescr(self.metainterp_sd, self.original_greenkey) + self.copy_all_attrbutes_into(res) return res class ResumeGuardForcedDescr(ResumeGuardDescr): - def handle_fail(self, metainterp_sd): + def __init__(self, metainterp_sd, original_greenkey, jitdriver_sd): + ResumeGuardDescr.__init__(self, metainterp_sd, original_greenkey) + self.jitdriver_sd = jitdriver_sd + + def handle_fail(self, metainterp_sd, jitdriver_sd): # Failures of a GUARD_NOT_FORCED are never compiled, but # always just blackholed. First fish for the data saved when # the virtualrefs and virtualizable have been forced by @@ -343,7 +355,8 @@ all_virtuals = self.fetch_data(token) if all_virtuals is None: all_virtuals = [] - resume_in_blackhole(metainterp_sd, self, all_virtuals) + assert jitdriver_sd is self.jitdriver_sd + resume_in_blackhole(metainterp_sd, jitdriver_sd, self, all_virtuals) assert 0, "unreachable" @staticmethod @@ -358,7 +371,8 @@ def handle_async_forcing(self, force_token): from pypy.jit.metainterp.resume import force_from_resumedata metainterp_sd = self.metainterp_sd - all_virtuals = force_from_resumedata(metainterp_sd, self) + vinfo = self.jitdriver_sd.virtualizable_info + all_virtuals = force_from_resumedata(metainterp_sd, self, vinfo) # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED @@ -392,6 +406,13 @@ assert 0, "not found: %r" % (key,) return data + def _clone_if_mutable(self): + res = ResumeGuardForcedDescr(self.metainterp_sd, + self.original_greenkey, + self.jitdriver_sd) + self.copy_all_attrbutes_into(res) + return res + class AbstractResumeGuardCounters(object): # Completely custom algorithm for now: keep 5 pairs (value, counter), @@ -464,19 +485,19 @@ # a loop at all but ends in a jump to the target loop. It starts # with completely unoptimized arguments, as in the interpreter. metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd metainterp.history.inputargs = self.redkey - new_loop_token = make_loop_token(len(self.redkey)) + new_loop_token = make_loop_token(len(self.redkey), jitdriver_sd) new_loop.greenkey = self.original_greenkey new_loop.inputargs = self.redkey new_loop.token = new_loop_token send_loop_to_backend(metainterp_sd, new_loop, "entry bridge") # send the new_loop to warmspot.py, to be called directly the next time - metainterp_sd.state.attach_unoptimized_bridge_from_interp( + jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp( self.original_greenkey, new_loop_token) # store the new loop in compiled_merge_points too - glob = metainterp_sd.globaldata - old_loop_tokens = glob.get_compiled_merge_points( + old_loop_tokens = metainterp.get_compiled_merge_points( self.original_greenkey) # it always goes at the end of the list, as it is the most # general loop token @@ -500,10 +521,11 @@ # clone ops, as optimize_bridge can mutate the ops new_loop.operations = [op.clone() for op in metainterp.history.operations] metainterp_sd = metainterp.staticdata + state = metainterp.jitdriver_sd.warmstate try: - target_loop_token = metainterp_sd.state.optimize_bridge(metainterp_sd, - old_loop_tokens, - new_loop) + target_loop_token = state.optimize_bridge(metainterp_sd, + old_loop_tokens, + new_loop) except InvalidLoop: # XXX I am fairly convinced that optimize_bridge cannot actually raise # InvalidLoop Modified: pypy/trunk/pypy/jit/metainterp/history.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/history.py (original) +++ pypy/trunk/pypy/jit/metainterp/history.py Tue Jun 29 16:48:45 2010 @@ -125,9 +125,6 @@ def repr_of_descr(self): return '%r' % (self,) - def _clone_if_mutable(self): - return self - def get_arg_types(self): """ Implement in call descr. Must return a string of INT, REF and FLOAT ('i', 'r', 'f'). @@ -171,10 +168,18 @@ """ raise NotImplementedError + def _clone_if_mutable(self): + return self + def clone_if_mutable(self): + clone = self._clone_if_mutable() + if not we_are_translated(): + assert clone.__class__ is self.__class__ + return clone + class AbstractFailDescr(AbstractDescr): index = -1 - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdriver_sd): raise NotImplementedError def compile_and_attach(self, metainterp, new_loop): raise NotImplementedError @@ -694,6 +699,7 @@ generated assembler. """ terminating = False # see TerminatingLoopToken in compile.py + outermost_jitdriver_sd = None # specnodes = ... # and more data specified by the backend when the loop is compiled number = 0 Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Tue Jun 29 16:48:45 2010 @@ -56,6 +56,7 @@ self.parent_resumedata_snapshot = None self.parent_resumedata_frame_info_list = None + @specialize.arg(3) def copy_constants(self, registers, constants, ConstClass): """Copy jitcode.constants[0] to registers[255], jitcode.constants[1] to registers[254], @@ -68,7 +69,6 @@ assert j >= 0 registers[j] = ConstClass(constants[i]) i -= 1 - copy_constants._annspecialcase_ = 'specialize:arg(3)' def cleanup_registers(self): # To avoid keeping references alive, this cleans up the registers_r. @@ -80,6 +80,7 @@ # ------------------------------ # Decoding of the JitCode + @specialize.arg(4) def prepare_list_of_boxes(self, outvalue, startindex, position, argcode): assert argcode in 'IRF' code = self.bytecode @@ -92,7 +93,6 @@ elif argcode == 'F': reg = self.registers_f[index] else: raise AssertionError(argcode) outvalue[startindex+i] = reg - prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)' def get_current_position_info(self): return self.jitcode.get_live_vars_info(self.pc) @@ -516,6 +516,8 @@ def _nonstandard_virtualizable(self, pc, box): # returns True if 'box' is actually not the "standard" virtualizable # that is stored in metainterp.virtualizable_boxes[-1] + if self.metainterp.jitdriver_sd.virtualizable_info is None: + return True # can occur in case of multiple JITs standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is box: return False @@ -528,17 +530,11 @@ return not isstandard def _get_virtualizable_field_index(self, fielddescr): - vinfo = self.metainterp.staticdata.virtualizable_info + # Get the index of a fielddescr. Must only be called for + # the "standard" virtualizable. + vinfo = self.metainterp.jitdriver_sd.virtualizable_info return vinfo.static_field_by_descrs[fielddescr] - def _get_virtualizable_array_field_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.array_field_descrs[index] - - def _get_virtualizable_array_descr(self, index): - vinfo = self.metainterp.staticdata.virtualizable_info - return vinfo.array_descrs[index] - @arguments("orgpc", "box", "descr") def _opimpl_getfield_vable(self, pc, box, fielddescr): if self._nonstandard_virtualizable(pc, box): @@ -566,8 +562,11 @@ opimpl_setfield_vable_f = _opimpl_setfield_vable def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox): + # Get the index of an array item: the index'th of the array + # described by arrayfielddescr. Must only be called for + # the "standard" virtualizable. indexbox = self.implement_guard_value(pc, indexbox) - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[arrayfielddescr] @@ -616,7 +615,7 @@ arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC, fdescr, box) return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox) - vinfo = self.metainterp.staticdata.virtualizable_info + vinfo = self.metainterp.jitdriver_sd.virtualizable_info virtualizable_box = self.metainterp.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) arrayindex = vinfo.array_field_by_descrs[fdescr] @@ -665,12 +664,12 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("boxes3", "boxes3") - def _opimpl_recursive_call(self, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes - metainterp_sd = self.metainterp.staticdata - portal_code = metainterp_sd.portal_code - warmrunnerstate = metainterp_sd.state + portal_code = targetjitdriver_sd.mainjitcode + warmrunnerstate = targetjitdriver_sd.warmstate token = None if warmrunnerstate.inlining: if warmrunnerstate.can_inline_callable(greenboxes): @@ -679,12 +678,13 @@ token = warmrunnerstate.get_assembler_token(greenboxes) # verify that we have all green args, needed to make sure # that assembler that we call is still correct - self.verify_green_args(greenboxes) + self.verify_green_args(targetjitdriver_sd, greenboxes) # - k = llmemory.cast_ptr_to_adr(metainterp_sd._portal_runner_ptr) + k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) return self.do_residual_call(funcbox, portal_code.calldescr, - allboxes, assembler_call_token=token) + allboxes, assembler_call_token=token, + assembler_call_jd=targetjitdriver_sd) opimpl_recursive_call_i = _opimpl_recursive_call opimpl_recursive_call_r = _opimpl_recursive_call @@ -768,24 +768,27 @@ self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) return clsbox - @arguments() - def opimpl_can_enter_jit(self): + @arguments("int") + def opimpl_can_enter_jit(self, jdindex): if self.metainterp.in_recursion: from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit raise CannotInlineCanEnterJit() + assert jdindex == self.metainterp.jitdriver_sd.index, ( + "found a can_enter_jit that does not match the current jitdriver") self.metainterp.seen_can_enter_jit = True - def verify_green_args(self, varargs): - num_green_args = self.metainterp.staticdata.num_green_args + def verify_green_args(self, jitdriver_sd, varargs): + num_green_args = jitdriver_sd.num_green_args assert len(varargs) == num_green_args for i in range(num_green_args): assert isinstance(varargs[i], Const) - @arguments("orgpc", "boxes3", "boxes3") - def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes): - self.verify_green_args(greenboxes) + @arguments("orgpc", "int", "boxes3", "boxes3") + def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes): + jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] + self.verify_green_args(jitdriver_sd, greenboxes) # xxx we may disable the following line in some context later - self.debug_merge_point(greenboxes) + self.debug_merge_point(jitdriver_sd, greenboxes) if self.metainterp.seen_can_enter_jit: self.metainterp.seen_can_enter_jit = False # Assert that it's impossible to arrive here with in_recursion @@ -793,6 +796,7 @@ # to True by opimpl_can_enter_jit, which should be executed # just before opimpl_jit_merge_point (no recursion inbetween). assert not self.metainterp.in_recursion + assert jitdriver_sd is self.metainterp.jitdriver_sd # Set self.pc to point to jit_merge_point instead of just after: # if reached_can_enter_jit() raises SwitchToBlackhole, then the # pc is still at the jit_merge_point, which is a point that is @@ -802,10 +806,9 @@ self.metainterp.reached_can_enter_jit(greenboxes, redboxes) self.pc = saved_pc - def debug_merge_point(self, greenkey): + def debug_merge_point(self, jitdriver_sd, greenkey): # debugging: produce a DEBUG_MERGE_POINT operation - sd = self.metainterp.staticdata - loc = sd.state.get_location_str(greenkey) + loc = jitdriver_sd.warmstate.get_location_str(greenkey) debug_print(loc) constloc = self.metainterp.cpu.ts.conststr(loc) self.metainterp.history.record(rop.DEBUG_MERGE_POINT, @@ -948,14 +951,15 @@ original_greenkey = metainterp.resumekey.original_greenkey if opnum == rop.GUARD_NOT_FORCED: resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd, - original_greenkey) + original_greenkey, + metainterp.jitdriver_sd) else: resumedescr = compile.ResumeGuardDescr(metainterp_sd, original_greenkey) guard_op = metainterp.history.record(opnum, moreargs, None, descr=resumedescr) virtualizable_boxes = None - if metainterp.staticdata.virtualizable_info is not None: + if metainterp.jitdriver_sd.virtualizable_info is not None: virtualizable_boxes = metainterp.virtualizable_boxes saved_pc = self.pc if resumepc >= 0: @@ -1007,7 +1011,8 @@ return resbox def do_residual_call(self, funcbox, descr, argboxes, - assembler_call_token=None): + assembler_call_token=None, + assembler_call_jd=None): # First build allboxes: it may need some reordering from the # list provided in argboxes, depending on the order in which # the arguments are expected by the function @@ -1052,7 +1057,8 @@ rop.CALL_MAY_FORCE, allboxes, descr=descr) self.metainterp.vrefs_after_residual_call() if assembler_call_token is not None: - self.metainterp.direct_assembler_call(assembler_call_token) + self.metainterp.direct_assembler_call(assembler_call_token, + assembler_call_jd) if resbox is not None: self.make_result_of_lastop(resbox) self.metainterp.vable_after_residual_call() @@ -1137,6 +1143,11 @@ self._addr2name_keys = [key for key, value in list_of_addr2name] self._addr2name_values = [value for key, value in list_of_addr2name] + def setup_jitdrivers_sd(self, optimizer): + if optimizer is not None: + for jd in self.jitdrivers_sd: + jd.warmstate.set_param_optimizer(optimizer) + def finish_setup(self, codewriter, optimizer=None): from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self) @@ -1147,28 +1158,21 @@ self.setup_indirectcalltargets(asm.indirectcalltargets) self.setup_list_of_addr2name(asm.list_of_addr2name) # - self.portal_code = codewriter.mainjitcode - self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr + self.jitdrivers_sd = codewriter.callcontrol.jitdrivers_sd self.virtualref_info = codewriter.callcontrol.virtualref_info - self.virtualizable_info = codewriter.callcontrol.virtualizable_info - RESULT = codewriter.portal_graph.getreturnvar().concretetype - self.result_type = history.getkind(RESULT) + self.setup_jitdrivers_sd(optimizer) # # store this information for fastpath of call_assembler - name = self.result_type - tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) - num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) - setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) + # (only the paths that can actually be taken) + for jd in self.jitdrivers_sd: + name = {history.INT: 'int', + history.REF: 'ref', + history.FLOAT: 'float', + history.VOID: 'void'}[jd.result_type] + tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name) + num = self.cpu.get_fail_descr_number(tokens[0].finishdescr) + setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num) # - warmrunnerdesc = self.warmrunnerdesc - if warmrunnerdesc is not None: - self.num_green_args = warmrunnerdesc.num_green_args - self.state = warmrunnerdesc.state - if optimizer is not None: - self.state.set_param_optimizer(optimizer) - else: - self.num_green_args = 0 - self.state = None self.globaldata = MetaInterpGlobalData(self) def _setup_once(self): @@ -1189,8 +1193,7 @@ # Build the dictionary at run-time. This is needed # because the keys are function/class addresses, so they # can change from run to run. - k = llmemory.cast_ptr_to_adr(self._portal_runner_ptr) - d = {k: 'recursive call'} + d = {} keys = self._addr2name_keys values = self._addr2name_values for i in range(len(keys)): @@ -1248,47 +1251,31 @@ self.loopnumbering = 0 self.resume_virtuals = {} self.resume_virtuals_not_translated = [] - # - state = staticdata.state - if state is not None: - self.jit_cell_at_key = state.jit_cell_at_key - else: - # for tests only; not RPython - class JitCell: - compiled_merge_points = None - _jitcell_dict = {} - def jit_cell_at_key(greenkey): - greenkey = tuple(greenkey) - return _jitcell_dict.setdefault(greenkey, JitCell()) - self.jit_cell_at_key = jit_cell_at_key - - def get_compiled_merge_points(self, greenkey): - cell = self.jit_cell_at_key(greenkey) - if cell.compiled_merge_points is None: - cell.compiled_merge_points = [] - return cell.compiled_merge_points # ____________________________________________________________ class MetaInterp(object): in_recursion = 0 - def __init__(self, staticdata): + def __init__(self, staticdata, jitdriver_sd): self.staticdata = staticdata self.cpu = staticdata.cpu + self.jitdriver_sd = jitdriver_sd + # Note: self.jitdriver_sd is the JitDriverStaticData that corresponds + # to the current loop -- the outermost one. Be careful, because + # during recursion we can also see other jitdrivers. self.portal_trace_positions = [] self.free_frames_list = [] self.last_exc_value_box = None def perform_call(self, jitcode, boxes, greenkey=None): # causes the metainterp to enter the given subfunction - # with a special case for recursive portal calls f = self.newframe(jitcode, greenkey) f.setup_call(boxes) raise ChangeFrame def newframe(self, jitcode, greenkey=None): - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: self.in_recursion += 1 if greenkey is not None: self.portal_trace_positions.append( @@ -1303,7 +1290,7 @@ def popframe(self): frame = self.framestack.pop() - if frame.jitcode is self.staticdata.portal_code: + if frame.jitcode.is_portal: self.in_recursion -= 1 if frame.greenkey is not None: self.portal_trace_positions.append( @@ -1327,14 +1314,15 @@ except SwitchToBlackhole, stb: self.aborted_tracing(stb.reason) sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert resultbox is None raise sd.DoneWithThisFrameVoid() - elif sd.result_type == 'int': + elif result_type == history.INT: raise sd.DoneWithThisFrameInt(resultbox.getint()) - elif sd.result_type == 'ref': + elif result_type == history.REF: raise sd.DoneWithThisFrameRef(self.cpu, resultbox.getref_base()) - elif sd.result_type == 'float': + elif result_type == history.FLOAT: raise sd.DoneWithThisFrameFloat(resultbox.getfloat()) else: assert False @@ -1364,14 +1352,17 @@ in_recursion = -1 for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + assert jitcode.is_portal == len([ + jd for jd in self.staticdata.jitdrivers_sd + if jd.mainjitcode is jitcode]) + if jitcode.is_portal: in_recursion += 1 if in_recursion != self.in_recursion: print "in_recursion problem!!!" print in_recursion, self.in_recursion for frame in self.framestack: jitcode = frame.jitcode - if jitcode is self.staticdata.portal_code: + if jitcode.is_portal: print "P", else: print " ", @@ -1379,7 +1370,6 @@ raise AssertionError def create_empty_history(self): - warmrunnerstate = self.staticdata.state self.history = history.History() self.staticdata.stats.set_history(self.history) @@ -1489,12 +1479,11 @@ self.resumekey.reset_counter_from_failure() def blackhole_if_trace_too_long(self): - warmrunnerstate = self.staticdata.state + warmrunnerstate = self.jitdriver_sd.warmstate if len(self.history.operations) > warmrunnerstate.trace_limit: greenkey_of_huge_function = self.find_biggest_function() self.portal_trace_positions = None if greenkey_of_huge_function is not None: - warmrunnerstate = self.staticdata.state warmrunnerstate.disable_noninlinable_function( greenkey_of_huge_function) raise SwitchToBlackhole(ABORT_TOO_LONG) @@ -1521,21 +1510,27 @@ self.staticdata.log(sys.exc_info()[0].__name__) raise - def compile_and_run_once(self, *args): + @specialize.arg(1) + def compile_and_run_once(self, jitdriver_sd, *args): + # NB. we pass explicity 'jitdriver_sd' around here, even though it + # is also available as 'self.jitdriver_sd', because we need to + # specialize this function and a few other ones for the '*args'. debug_start('jit-tracing') self.staticdata._setup_once() self.staticdata.profiler.start_tracing() + assert jitdriver_sd is self.jitdriver_sd self.create_empty_history() try: - return self._compile_and_run_once(*args) + original_boxes = self.initialize_original_boxes(jitdriver_sd,*args) + return self._compile_and_run_once(original_boxes) finally: self.staticdata.profiler.end_tracing() debug_stop('jit-tracing') - def _compile_and_run_once(self, *args): - original_boxes = self.initialize_state_from_start(*args) + def _compile_and_run_once(self, original_boxes): + self.initialize_state_from_start(original_boxes) self.current_merge_points = [(original_boxes, 0)] - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args original_greenkey = original_boxes[:num_green_args] redkey = original_boxes[num_green_args:] self.resumekey = compile.ResumeFromInterpDescr(original_greenkey, @@ -1602,7 +1597,7 @@ self.remove_consts_and_duplicates(redboxes, len(redboxes), duplicates) live_arg_boxes = greenboxes + redboxes - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: # we use pop() to remove the last item, which is the virtualizable # itself self.remove_consts_and_duplicates(self.virtualizable_boxes, @@ -1624,11 +1619,12 @@ # Search in current_merge_points for original_boxes with compatible # green keys, representing the beginning of the same loop as the one # we end now. - + + num_green_args = self.jitdriver_sd.num_green_args for j in range(len(self.current_merge_points)-1, -1, -1): original_boxes, start = self.current_merge_points[j] assert len(original_boxes) == len(live_arg_boxes) or start < 0 - for i in range(self.staticdata.num_green_args): + for i in range(num_green_args): box1 = original_boxes[i] box2 = live_arg_boxes[i] assert isinstance(box1, Const) @@ -1651,7 +1647,7 @@ def designate_target_loop(self, gmp): loop_token = gmp.target_loop_token - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args residual_args = self.get_residual_args(loop_token.specnodes, gmp.argboxes[num_green_args:]) history.set_future_values(self.cpu, residual_args) @@ -1692,12 +1688,17 @@ from pypy.jit.metainterp.resoperation import opname raise NotImplementedError(opname[opnum]) + def get_compiled_merge_points(self, greenkey): + cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey) + if cell.compiled_merge_points is None: + cell.compiled_merge_points = [] + return cell.compiled_merge_points + def compile(self, original_boxes, live_arg_boxes, start): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop_token = compile.compile_new_loop(self, old_loop_tokens, greenkey, start) @@ -1706,10 +1707,9 @@ self.history.operations.pop() # remove the JUMP def compile_bridge(self, live_arg_boxes): - num_green_args = self.staticdata.num_green_args + num_green_args = self.jitdriver_sd.num_green_args greenkey = live_arg_boxes[:num_green_args] - glob = self.staticdata.globaldata - old_loop_tokens = glob.get_compiled_merge_points(greenkey) + old_loop_tokens = self.get_compiled_merge_points(greenkey) if len(old_loop_tokens) == 0: return self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) @@ -1723,17 +1723,18 @@ self.gen_store_back_in_virtualizable() # temporarily put a JUMP to a pseudo-loop sd = self.staticdata - if sd.result_type == 'void': + result_type = self.jitdriver_sd.result_type + if result_type == history.VOID: assert exitbox is None exits = [] loop_tokens = sd.loop_tokens_done_with_this_frame_void - elif sd.result_type == 'int': + elif result_type == history.INT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_int - elif sd.result_type == 'ref': + elif result_type == history.REF: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_ref - elif sd.result_type == 'float': + elif result_type == history.FLOAT: exits = [exitbox] loop_tokens = sd.loop_tokens_done_with_this_frame_float else: @@ -1765,26 +1766,32 @@ specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args - def _initialize_from_start(self, original_boxes, num_green_args, *args): + @specialize.arg(1) + def initialize_original_boxes(self, jitdriver_sd, *args): + original_boxes = [] + self._fill_original_boxes(jitdriver_sd, original_boxes, + jitdriver_sd.num_green_args, *args) + return original_boxes + + @specialize.arg(1) + def _fill_original_boxes(self, jitdriver_sd, original_boxes, + num_green_args, *args): if args: from pypy.jit.metainterp.warmstate import wrap box = wrap(self.cpu, args[0], num_green_args > 0) original_boxes.append(box) - self._initialize_from_start(original_boxes, num_green_args-1, - *args[1:]) + self._fill_original_boxes(jitdriver_sd, original_boxes, + num_green_args-1, *args[1:]) - def initialize_state_from_start(self, *args): - self.in_recursion = -1 # always one portal around - num_green_args = self.staticdata.num_green_args - original_boxes = [] - self._initialize_from_start(original_boxes, num_green_args, *args) + def initialize_state_from_start(self, original_boxes): # ----- make a new frame ----- + self.in_recursion = -1 # always one portal around self.framestack = [] - f = self.newframe(self.staticdata.portal_code) + f = self.newframe(self.jitdriver_sd.mainjitcode) f.setup_call(original_boxes) + assert self.in_recursion == 0 self.virtualref_boxes = [] self.initialize_virtualizable(original_boxes) - return original_boxes def initialize_state_from_guard_failure(self, resumedescr): # guard failure: rebuild a complete MIFrame stack @@ -1794,9 +1801,11 @@ self.history.inputargs = [box for box in inputargs_and_holes if box] def initialize_virtualizable(self, original_boxes): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: - virtualizable_box = original_boxes[vinfo.index_of_virtualizable] + index = (self.jitdriver_sd.num_green_args + + self.jitdriver_sd.index_of_virtualizable) + virtualizable_box = original_boxes[index] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) # The field 'virtualizable_boxes' is not even present # if 'virtualizable_info' is None. Check for that first. @@ -1807,7 +1816,7 @@ self.initialize_virtualizable_enter() def initialize_virtualizable_enter(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.clear_vable_token(virtualizable) @@ -1821,7 +1830,7 @@ # the FORCE_TOKEN is already set at runtime in each vref when # it is created, by optimizeopt.py. # - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1847,7 +1856,7 @@ self.stop_tracking_virtualref(i) def vable_after_residual_call(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1898,7 +1907,7 @@ assert self.last_exc_value_box is None def rebuild_state_after_failure(self, resumedescr): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info self.framestack = [] boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo) inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists @@ -1923,24 +1932,19 @@ virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) assert not virtualizable.vable_token - if 0: ## self._already_allocated_resume_virtuals is not None: - # resuming from a ResumeGuardForcedDescr: load the new values - # currently stored on the virtualizable fields - self.load_fields_from_virtualizable() - else: - # normal case: fill the virtualizable with the local boxes - self.synchronize_virtualizable() + # fill the virtualizable with the local boxes + self.synchronize_virtualizable() return inputargs_and_holes def check_synchronized_virtualizable(self): if not we_are_translated(): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.check_boxes(virtualizable, self.virtualizable_boxes) def synchronize_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) vinfo.write_boxes(virtualizable, self.virtualizable_boxes) @@ -1949,7 +1953,7 @@ # Force a reload of the virtualizable fields into the local # boxes (called only in escaping cases). Only call this function # just before SwitchToBlackhole. - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) @@ -1958,7 +1962,7 @@ self.virtualizable_boxes.append(virtualizable_box) def gen_store_back_in_virtualizable(self): - vinfo = self.staticdata.virtualizable_info + vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: # xxx only write back the fields really modified vbox = self.virtualizable_boxes[-1] @@ -1979,8 +1983,7 @@ abox, ConstInt(j), itembox) assert i + 1 == len(self.virtualizable_boxes) - def gen_load_from_other_virtualizable(self, vbox): - vinfo = self.staticdata.virtualizable_info + def gen_load_from_other_virtualizable(self, vinfo, vbox): boxes = [] assert vinfo is not None for i in range(vinfo.num_static_extra_boxes): @@ -2004,7 +2007,7 @@ for i in range(len(boxes)): if boxes[i] is oldbox: boxes[i] = newbox - if self.staticdata.virtualizable_info is not None: + if self.jitdriver_sd.virtualizable_info is not None: boxes = self.virtualizable_boxes for i in range(len(boxes)): if boxes[i] is oldbox: @@ -2052,18 +2055,19 @@ op.args = [resbox_as_const] + op.args return resbox - def direct_assembler_call(self, token): + def direct_assembler_call(self, token, targetjitdriver_sd): """ Generate a direct call to assembler for portal entry point, patching the CALL_MAY_FORCE that occurred just now. """ op = self.history.operations.pop() assert op.opnum == rop.CALL_MAY_FORCE - num_green_args = self.staticdata.num_green_args + num_green_args = targetjitdriver_sd.num_green_args args = op.args[num_green_args + 1:] - if self.staticdata.virtualizable_info is not None: - vindex = self.staticdata.virtualizable_info.index_of_virtualizable - vbox = args[vindex - num_green_args] - args = args + self.gen_load_from_other_virtualizable(vbox) + vinfo = targetjitdriver_sd.virtualizable_info + if vinfo is not None: + index = targetjitdriver_sd.index_of_virtualizable + vbox = args[index] + args = args + self.gen_load_from_other_virtualizable(vinfo, vbox) # ^^^ and not "+=", which makes 'args' a resizable list op.opnum = rop.CALL_ASSEMBLER op.args = args @@ -2166,6 +2170,16 @@ position = position3 + 1 + length3 elif argtype == "orgpc": value = orgpc + elif argtype == "int": + argcode = argcodes[next_argcode] + next_argcode = next_argcode + 1 + if argcode == 'i': + value = self.registers_i[ord(code[position])].getint() + elif argcode == 'c': + value = signedord(code[position]) + else: + raise AssertionError("bad argcode") + position += 1 else: raise AssertionError("bad argtype: %r" % (argtype,)) args += (value,) Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resoperation.py (original) +++ pypy/trunk/pypy/jit/metainterp/resoperation.py Tue Jun 29 16:48:45 2010 @@ -34,7 +34,7 @@ def clone(self): descr = self.descr if descr is not None: - descr = descr._clone_if_mutable() + descr = descr.clone_if_mutable() op = ResOperation(self.opnum, self.args, self.result, descr) op.fail_args = self.fail_args if not we_are_translated(): Modified: pypy/trunk/pypy/jit/metainterp/resume.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resume.py (original) +++ pypy/trunk/pypy/jit/metainterp/resume.py Tue Jun 29 16:48:45 2010 @@ -709,11 +709,11 @@ # ---------- when resuming for blackholing, get direct values ---------- -def blackhole_from_resumedata(blackholeinterpbuilder, storage, +def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage, all_virtuals=None): resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage, all_virtuals) - vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info + vinfo = jitdriver_sd.virtualizable_info vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info resumereader.consume_vref_and_vable(vrefinfo, vinfo) # @@ -745,10 +745,9 @@ resumereader.done() return firstbh -def force_from_resumedata(metainterp_sd, storage): +def force_from_resumedata(metainterp_sd, storage, vinfo=None): resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage) resumereader.handling_async_forcing() - vinfo = metainterp_sd.virtualizable_info vrefinfo = metainterp_sd.virtualref_info resumereader.consume_vref_and_vable(vrefinfo, vinfo) return resumereader.virtuals Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Tue Jun 29 16:48:45 2010 @@ -16,10 +16,18 @@ from pypy.jit.codewriter import support, codewriter from pypy.jit.metainterp import simple_optimize + class FakeJitCell: + compiled_merge_points = None + class FakeWarmRunnerState: def attach_unoptimized_bridge_from_interp(self, greenkey, newloop): pass + def jit_cell_at_key(self, greenkey): + assert greenkey == [] + return self._cell + _cell = FakeJitCell() + # pick the optimizer this way optimize_loop = staticmethod(simple_optimize.optimize_loop) optimize_bridge = staticmethod(simple_optimize.optimize_bridge) @@ -30,14 +38,24 @@ func._jit_unroll_safe_ = True rtyper = support.annotate(func, values, type_system=type_system) graphs = rtyper.annotator.translator.graphs + result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0] + + class FakeJitDriverSD: + num_green_args = 0 + portal_graph = graphs[0] + virtualizable_info = None + result_type = result_kind + portal_runner_ptr = "???" + stats = history.Stats() cpu = CPUClass(rtyper, stats, None, False) - cw = codewriter.CodeWriter(cpu, graphs[0]) + cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()]) testself.cw = cw cw.find_all_graphs(JitPolicy()) # testself.warmrunnerstate = FakeWarmRunnerState() testself.warmrunnerstate.cpu = cpu + FakeJitDriverSD.warmstate = testself.warmrunnerstate if hasattr(testself, 'finish_setup_for_interp_operations'): testself.finish_setup_for_interp_operations() # @@ -62,7 +80,8 @@ count_f += 1 else: raise TypeError(T) - blackholeinterp.setposition(cw.mainjitcode, 0) + [jitdriver_sd] = cw.callcontrol.jitdrivers_sd + blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0) blackholeinterp.run() return blackholeinterp._final_result_anytype() @@ -78,16 +97,15 @@ cw = testself.cw opt = history.Options(listops=True) metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt) - metainterp_sd.finish_setup(cw, optimizer="bogus") - metainterp_sd.state = testself.warmrunnerstate - metainterp_sd.state.cpu = metainterp_sd.cpu - metainterp = pyjitpl.MetaInterp(metainterp_sd) + metainterp_sd.finish_setup(cw) + [jitdriver_sd] = metainterp_sd.jitdrivers_sd + metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd) metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame testself.metainterp = metainterp try: - metainterp.compile_and_run_once(*args) + metainterp.compile_and_run_once(jitdriver_sd, *args) except DoneWithThisFrame, e: #if conftest.option.view: # metainterp.stats.view() @@ -864,8 +882,9 @@ translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=self.CPUClass) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(0) # for tests + state = warmrunnerdesc.jitdrivers_sd[0].warmstate + state.set_param_threshold(3) # for tests + state.set_param_trace_eagerness(0) # for tests warmrunnerdesc.finish() for n, k in [(20, 0), (20, 1)]: interp.eval_graph(graph, [n, k]) Modified: pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py Tue Jun 29 16:48:45 2010 @@ -42,7 +42,7 @@ blackholeinterp.setarg_i(0, 40) blackholeinterp.setarg_i(1, 2) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_const(): jitcode = JitCode("test") @@ -54,7 +54,7 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(1, 6) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_bigconst(): jitcode = JitCode("test") @@ -66,7 +66,7 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(1, 10000) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_simple_loop(): jitcode = JitCode("test") @@ -85,7 +85,7 @@ blackholeinterp.setarg_i(0x16, 6) # %i0 blackholeinterp.setarg_i(0x17, 100) # %i1 blackholeinterp.run() - assert blackholeinterp.final_result_i() == 100+6+5+4+3 + assert blackholeinterp._final_result_anytype() == 100+6+5+4+3 def test_simple_exception(): jitcode = JitCode("test") @@ -104,12 +104,12 @@ blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(0x9, 100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 200 + assert blackholeinterp._final_result_anytype() == 200 # blackholeinterp.setposition(jitcode, 0) blackholeinterp.setarg_i(0x9, -100) blackholeinterp.run() - assert blackholeinterp.final_result_i() == 42 + assert blackholeinterp._final_result_anytype() == 42 def test_convert_and_run_from_pyjitpl(): class MyMIFrame: Modified: pypy/trunk/pypy/jit/metainterp/test/test_compile.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_compile.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_compile.py Tue Jun 29 16:48:45 2010 @@ -51,14 +51,14 @@ logger_noopt = FakeLogger() logger_ops = FakeLogger() - state = FakeState() stats = Stats() profiler = jitprof.EmptyProfiler() def log(self, msg, event_kind=None): pass class FakeMetaInterp: - pass + class jitdriver_sd: + warmstate = FakeState() def test_compile_new_loop(): cpu = FakeCPU() Modified: pypy/trunk/pypy/jit/metainterp/test/test_list.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_list.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_list.py Tue Jun 29 16:48:45 2010 @@ -143,6 +143,51 @@ assert res == 7 self.check_loops(call=0) + def test_fold_getitem_1(self): + jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total']) + def f(n): + l = [100, n, 300, n, 500] + total = 0 + pc = n + while True: + jitdriver.can_enter_jit(l=l, pc=pc, n=n, total=total) + jitdriver.jit_merge_point(l=l, pc=pc, n=n, total=total) + total += l[pc] + if total > 10000: + return total + pc -= 1 + if pc < 0: + pc = n + + res = self.meta_interp(f, [4], listops=True) + assert res == f(4) + self.check_loops(call=0) + + def test_fold_getitem_2(self): + jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total', 'x']) + class X: + pass + def f(n): + l = [100, n, 300, n, 500] + total = 0 + x = X() + x.pc = n + while True: + pc = x.pc + jitdriver.can_enter_jit(l=l, pc=pc, n=n, total=total, x=x) + jitdriver.jit_merge_point(l=l, pc=pc, n=n, total=total, x=x) + x.pc = pc + total += l[x.pc] + if total > 10000: + return total + x.pc -= 1 + if x.pc < 0: + x.pc = n + + res = self.meta_interp(f, [4], listops=True) + assert res == f(4) + self.check_loops(call=0, getfield_gc=0) + class TestOOtype(ListTests, OOJitMixin): pass Modified: pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py Tue Jun 29 16:48:45 2010 @@ -17,9 +17,8 @@ portal.setup(None) class FakeStaticData: cpu = None - portal_code = portal - metainterp = pyjitpl.MetaInterp(FakeStaticData()) + metainterp = pyjitpl.MetaInterp(FakeStaticData(), None) metainterp.framestack = [] class FakeHistory: operations = [] @@ -59,7 +58,7 @@ assert isinstance(box, referencebox.clonebox().__class__) assert box.value == referencebox.value return True - metainterp = pyjitpl.MetaInterp(FakeStaticData()) + metainterp = pyjitpl.MetaInterp(FakeStaticData(), None) metainterp.history = History() b1 = BoxInt(1) b2 = BoxInt(2) Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py Tue Jun 29 16:48:45 2010 @@ -128,8 +128,9 @@ from pypy.jit.metainterp import optimize - assert warmrunnerdescr.state.optimize_loop is optimize.optimize_loop - assert warmrunnerdescr.state.optimize_bridge is optimize.optimize_bridge + state = warmrunnerdescr.jitdrivers_sd[0].warmstate + assert state.optimize_loop is optimize.optimize_loop + assert state.optimize_bridge is optimize.optimize_bridge def test_static_debug_level(self, capfd): py.test.skip("debug_level is being deprecated") @@ -294,7 +295,7 @@ def __init__(self, no): self.no = no - def handle_fail(self, metainterp_sd): + def handle_fail(self, metainterp_sd, jitdrivers_sd): if self.no == 0: raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3) if self.no == 1: @@ -355,12 +356,13 @@ def test_call_helper(self): from pypy.rpython.llinterp import LLException - - assert self.desc.assembler_call_helper(0, 0) == 3 - assert self.desc.assembler_call_helper(1, 0) == 10 - assert self.desc.assembler_call_helper(2, 0) == 10 + + [jd] = self.desc.jitdrivers_sd + assert jd._assembler_call_helper(0, 0) == 3 + assert jd._assembler_call_helper(1, 0) == 10 + assert jd._assembler_call_helper(2, 0) == 10 try: - self.desc.assembler_call_helper(3, 0) + jd._assembler_call_helper(3, 0) except LLException, lle: assert lle[0] == self.exc_vtable else: Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py Tue Jun 29 16:48:45 2010 @@ -4,10 +4,9 @@ from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.warmstate import wrap, unwrap from pypy.jit.metainterp.warmstate import equal_whatever, hash_whatever -from pypy.jit.metainterp.warmstate import WarmEnterState +from pypy.jit.metainterp.warmstate import WarmEnterState, JitCell from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr from pypy.jit.metainterp.history import ConstInt, ConstFloat, ConstPtr -from pypy.rlib.jit import BaseJitCell def test_unwrap(): @@ -58,14 +57,12 @@ def test_make_jitcell_getter_default(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - class FakeJitCell(BaseJitCell): - pass - state = WarmEnterState(FakeWarmRunnerDesc()) - get_jitcell = state._make_jitcell_getter_default(FakeJitCell) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + state = WarmEnterState(None, FakeJitDriverSD()) + get_jitcell = state._make_jitcell_getter_default() cell1 = get_jitcell(42, 42.5) - assert isinstance(cell1, FakeJitCell) + assert isinstance(cell1, JitCell) cell2 = get_jitcell(42, 42.5) assert cell1 is cell2 cell3 = get_jitcell(41, 42.5) @@ -73,10 +70,10 @@ assert cell1 is not cell3 is not cell4 is not cell1 def test_make_jitcell_getter(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Float] - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Float] + _get_jitcell_at_ptr = None + state = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = state.make_jitcell_getter() cell1 = get_jitcell(1.75) cell2 = get_jitcell(1.75) @@ -87,8 +84,6 @@ from pypy.rpython.typesystem import LowLevelTypeSystem class FakeRTyper: type_system = LowLevelTypeSystem.instance - class FakeJitCell(BaseJitCell): - pass celldict = {} def getter(x, y): return celldict.get((x, y)) @@ -102,14 +97,14 @@ lltype.Float], lltype.Void)) class FakeWarmRunnerDesc: rtyper = FakeRTyper() - cpu = None - get_jitcell_at_ptr = llhelper(GETTER, getter) - set_jitcell_at_ptr = llhelper(SETTER, setter) + class FakeJitDriverSD: + _get_jitcell_at_ptr = llhelper(GETTER, getter) + _set_jitcell_at_ptr = llhelper(SETTER, setter) # - state = WarmEnterState(FakeWarmRunnerDesc()) - get_jitcell = state._make_jitcell_getter_custom(FakeJitCell) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) + get_jitcell = state._make_jitcell_getter_custom() cell1 = get_jitcell(5, 42.5) - assert isinstance(cell1, FakeJitCell) + assert isinstance(cell1, JitCell) assert cell1.x == 5 assert cell1.y == 42.5 cell2 = get_jitcell(5, 42.5) @@ -127,10 +122,11 @@ future_values[j] = "float", value class FakeWarmRunnerDesc: cpu = FakeCPU() - red_args_types = ["int", "float"] + class FakeJitDriverSD: + _red_args_types = ["int", "float"] virtualizable_info = None # - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) set_future_values = state.make_set_future_values() set_future_values(5, 42.5) assert future_values == { @@ -140,19 +136,19 @@ assert set_future_values is state.make_set_future_values() def test_make_unwrap_greenkey(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + state = WarmEnterState(None, FakeJitDriverSD()) unwrap_greenkey = state.make_unwrap_greenkey() greenargs = unwrap_greenkey([ConstInt(42), ConstFloat(42.5)]) assert greenargs == (42, 42.5) assert type(greenargs[0]) is int def test_attach_unoptimized_bridge_from_interp(): - class FakeWarmRunnerDesc: - green_args_spec = [lltype.Signed, lltype.Float] - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _get_jitcell_at_ptr = None + state = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = state.make_jitcell_getter() state.attach_unoptimized_bridge_from_interp([ConstInt(5), ConstFloat(2.25)], @@ -162,14 +158,14 @@ assert cell1.entry_loop_token == "entry loop token" def test_make_jitdriver_callbacks_1(): - class FakeWarmRunnerDesc: - can_inline_ptr = None - get_printable_location_ptr = None - confirm_enter_jit_ptr = None - green_args_spec = [lltype.Signed, lltype.Float] + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = None class FakeCell: dont_trace_here = False - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(None, FakeJitDriverSD()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter @@ -190,11 +186,12 @@ dont_trace_here = False class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = llhelper(CAN_INLINE, can_inline) - get_printable_location_ptr = None - confirm_enter_jit_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = llhelper(CAN_INLINE, can_inline) + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = None + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) def jit_getter(*args): return FakeCell() state.jit_getter = jit_getter @@ -211,12 +208,13 @@ lltype.Ptr(rstr.STR))) class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = None - get_printable_location_ptr = llhelper(GET_LOCATION, get_location) - confirm_enter_jit_ptr = None - get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = llhelper(GET_LOCATION, get_location) + _confirm_enter_jit_ptr = None + _get_jitcell_at_ptr = None + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) state.make_jitdriver_callbacks() res = state.get_location_str([ConstInt(5), ConstFloat(42.5)]) assert res == "hi there" @@ -231,13 +229,14 @@ lltype.Signed], lltype.Bool)) class FakeWarmRunnerDesc: rtyper = None - green_args_spec = [lltype.Signed, lltype.Float] - can_inline_ptr = None - get_printable_location_ptr = None - confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit) - get_jitcell_at_ptr = None + class FakeJitDriverSD: + _green_args_spec = [lltype.Signed, lltype.Float] + _can_inline_ptr = None + _get_printable_location_ptr = None + _confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit) + _get_jitcell_at_ptr = None - state = WarmEnterState(FakeWarmRunnerDesc()) + state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) state.make_jitdriver_callbacks() res = state.confirm_enter_jit(5, 42.5, 3) assert res is True Modified: pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py Tue Jun 29 16:48:45 2010 @@ -20,6 +20,7 @@ # - profiler # - full optimizer # - jitdriver hooks + # - two JITs class Frame(object): _virtualizable2_ = ['i'] @@ -61,14 +62,28 @@ frame.i -= 2 frame.i -= 1 return total * 10 - res = ll_meta_interp(f, [40], CPUClass=self.CPUClass, + # + myjitdriver2 = JitDriver(greens = ['g'], reds = ['m', 'x'], + can_inline = lambda *args: False) + def f2(g, m, x): + while m > 0: + myjitdriver2.can_enter_jit(g=g, m=m, x=x) + myjitdriver2.jit_merge_point(g=g, m=m, x=x) + m -= 1 + x += 3 + return x + # + def main(i, j): + return f(i) - f2(i+j, i, j) + res = ll_meta_interp(main, [40, 5], CPUClass=self.CPUClass, type_system=self.type_system) - assert res == f(40) - res = rpython_ll_meta_interp(f, [40], loops=2, CPUClass=self.CPUClass, + assert res == main(40, 5) + res = rpython_ll_meta_interp(main, [40, 5], loops=2, + CPUClass=self.CPUClass, type_system=self.type_system, optimizer=OPTIMIZER_FULL, ProfilerClass=Profiler) - assert res == f(40) + assert res == main(40, 5) def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) Modified: pypy/trunk/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/trunk/pypy/jit/metainterp/virtualizable.py Tue Jun 29 16:48:45 2010 @@ -14,9 +14,8 @@ TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler TOKEN_TRACING_RESCALL = -1 - def __init__(self, warmrunnerdesc): + def __init__(self, warmrunnerdesc, VTYPEPTR): self.warmrunnerdesc = warmrunnerdesc - jitdriver = warmrunnerdesc.jitdriver cpu = warmrunnerdesc.cpu if cpu.ts.name == 'ootype': import py @@ -24,11 +23,6 @@ self.cpu = cpu self.BoxArray = cpu.ts.BoxRef # - assert len(jitdriver.virtualizables) == 1 # for now - [vname] = jitdriver.virtualizables - index = len(jitdriver.greens) + jitdriver.reds.index(vname) - self.index_of_virtualizable = index - VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index] while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Tue Jun 29 16:48:45 2010 @@ -21,6 +21,7 @@ from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler from pypy.jit.metainterp.jitexc import JitException +from pypy.jit.metainterp.jitdriver import JitDriverStaticData from pypy.jit.codewriter import support, codewriter from pypy.jit.codewriter.policy import JitPolicy from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE @@ -44,8 +45,9 @@ no_stats = True, ProfilerClass = ProfilerClass, **kwds) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_debug(debug_level) + for jd in warmrunnerdesc.jitdrivers_sd: + jd.warmstate.set_param_inlining(inline) + jd.warmstate.set_param_debug(debug_level) warmrunnerdesc.finish() translator.warmrunnerdesc = warmrunnerdesc # for later debugging @@ -69,11 +71,12 @@ translator.config.translation.gc = "boehm" translator.config.translation.list_comprehension_operations = True warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests - warmrunnerdesc.state.set_param_trace_limit(trace_limit) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_debug(debug_level) + for jd in warmrunnerdesc.jitdrivers_sd: + jd.warmstate.set_param_threshold(3) # for tests + jd.warmstate.set_param_trace_eagerness(2) # for tests + jd.warmstate.set_param_trace_limit(trace_limit) + jd.warmstate.set_param_inlining(inline) + jd.warmstate.set_param_debug(debug_level) warmrunnerdesc.finish() res = interp.eval_graph(graph, args) if not kwds.get('translate_support_code', False): @@ -110,12 +113,11 @@ raise Exception("no can_enter_jit found!") return results -def find_jit_merge_point(graphs): +def find_jit_merge_points(graphs): results = _find_jit_marker(graphs, 'jit_merge_point') - if len(results) != 1: - raise Exception("found %d jit_merge_points, need exactly one!" % - (len(results),)) - return results[0] + if not results: + raise Exception("no jit_merge_point found!") + return results def find_set_param(graphs): return _find_jit_marker(graphs, 'set_param') @@ -146,8 +148,8 @@ pyjitpl._warmrunnerdesc = self # this is a global for debugging only! self.set_translator(translator) self.build_cpu(CPUClass, **kwds) - self.find_portal() - self.codewriter = codewriter.CodeWriter(self.cpu, self.portal_graph) + self.find_portals() + self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd) if policy is None: policy = JitPolicy() policy.set_supports_floats(self.cpu.supports_floats) @@ -158,35 +160,31 @@ self.prejit_optimizations(policy, graphs) self.build_meta_interp(ProfilerClass) - self.make_args_specification() + self.make_args_specifications() # from pypy.jit.metainterp.virtualref import VirtualRefInfo vrefinfo = VirtualRefInfo(self) self.codewriter.setup_vrefinfo(vrefinfo) - if self.jitdriver.virtualizables: - from pypy.jit.metainterp.virtualizable import VirtualizableInfo - self.virtualizable_info = VirtualizableInfo(self) - self.codewriter.setup_virtualizable_info(self.virtualizable_info) - else: - self.virtualizable_info = None # + self.make_virtualizable_infos() self.make_exception_classes() self.make_driverhook_graphs() - self.make_enter_function() - self.rewrite_jit_merge_point(policy) + self.make_enter_functions() + self.rewrite_jit_merge_points(policy) verbose = not self.cpu.translate_support_code self.codewriter.make_jitcodes(verbose=verbose) - self.rewrite_can_enter_jit() + self.rewrite_can_enter_jits() self.rewrite_set_param() self.rewrite_force_virtual(vrefinfo) self.add_finish() self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer) def finish(self): - vinfo = self.virtualizable_info - if vinfo is not None: - vinfo.finish() + vinfos = set([jd.virtualizable_info for jd in self.jitdrivers_sd]) + for vinfo in vinfos: + if vinfo is not None: + vinfo.finish() if self.cpu.translate_support_code: self.annhelper.finish() @@ -198,18 +196,27 @@ self.rtyper = translator.rtyper self.gcdescr = gc.get_description(translator.config) - def find_portal(self): + def find_portals(self): + self.jitdrivers_sd = [] graphs = self.translator.graphs - self.jit_merge_point_pos = find_jit_merge_point(graphs) - graph, block, pos = self.jit_merge_point_pos + for jit_merge_point_pos in find_jit_merge_points(graphs): + self.split_graph_and_record_jitdriver(*jit_merge_point_pos) + # + assert (len(set([jd.jitdriver for jd in self.jitdrivers_sd])) == + len(self.jitdrivers_sd)), \ + "there are multiple jit_merge_points with the same jitdriver" + + def split_graph_and_record_jitdriver(self, graph, block, pos): + jd = JitDriverStaticData() + jd._jit_merge_point_pos = (graph, block, pos) op = block.operations[pos] args = op.args[2:] s_binding = self.translator.annotator.binding - self.portal_args_s = [s_binding(v) for v in args] + jd._portal_args_s = [s_binding(v) for v in args] graph = copygraph(graph) graph.startblock.isstartblock = False - graph.startblock = support.split_before_jit_merge_point( - *find_jit_merge_point([graph])) + [jmpp] = find_jit_merge_points([graph]) + graph.startblock = support.split_before_jit_merge_point(*jmpp) graph.startblock.isstartblock = True # a crash in the following checkgraph() means that you forgot # to list some variable in greens=[] or reds=[] in JitDriver. @@ -218,12 +225,16 @@ assert isinstance(v, Variable) assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs()) self.translator.graphs.append(graph) - self.portal_graph = graph + jd.portal_graph = graph # it's a bit unbelievable to have a portal without func assert hasattr(graph, "func") graph.func._dont_inline_ = True graph.func._jit_unroll_safe_ = True - self.jitdriver = block.operations[pos].args[1].value + jd.jitdriver = block.operations[pos].args[1].value + jd.portal_runner_ptr = "" + jd.result_type = history.getkind(jd.portal_graph.getreturnvar() + .concretetype)[0] + self.jitdrivers_sd.append(jd) def check_access_directly_sanity(self, graphs): from pypy.translator.backendopt.inline import collect_called_graphs @@ -268,6 +279,27 @@ ProfilerClass=ProfilerClass, warmrunnerdesc=self) + def make_virtualizable_infos(self): + vinfos = {} + for jd in self.jitdrivers_sd: + if not jd.jitdriver.virtualizables: + jd.virtualizable_info = None + jd.index_of_virtualizable = -1 + continue + # + jitdriver = jd.jitdriver + assert len(jitdriver.virtualizables) == 1 # for now + [vname] = jitdriver.virtualizables + # XXX skip the Voids here too + jd.index_of_virtualizable = jitdriver.reds.index(vname) + # + index = jd.num_green_args + jd.index_of_virtualizable + VTYPEPTR = jd._JIT_ENTER_FUNCTYPE.ARGS[index] + if VTYPEPTR not in vinfos: + from pypy.jit.metainterp.virtualizable import VirtualizableInfo + vinfos[VTYPEPTR] = VirtualizableInfo(self, VTYPEPTR) + jd.virtualizable_info = vinfos[VTYPEPTR] + def make_exception_classes(self): class DoneWithThisFrameVoid(JitException): @@ -317,6 +349,8 @@ self.green_int, self.green_ref, self.green_float, self.red_int, self.red_ref, self.red_float) + # XXX there is no point any more to not just have the exceptions + # as globals self.DoneWithThisFrameVoid = DoneWithThisFrameVoid self.DoneWithThisFrameInt = DoneWithThisFrameInt self.DoneWithThisFrameRef = DoneWithThisFrameRef @@ -330,11 +364,15 @@ self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally - def make_enter_function(self): + def make_enter_functions(self): + for jd in self.jitdrivers_sd: + self.make_enter_function(jd) + + def make_enter_function(self, jd): from pypy.jit.metainterp.warmstate import WarmEnterState - state = WarmEnterState(self) + state = WarmEnterState(self, jd) maybe_compile_and_run = state.make_entry_point() - self.state = state + jd.warmstate = state def crash_in_jit(e): if not we_are_translated(): @@ -359,15 +397,16 @@ def maybe_enter_jit(*args): maybe_compile_and_run(*args) maybe_enter_jit._always_inline_ = True - self.maybe_enter_jit_fn = maybe_enter_jit + jd._maybe_enter_jit_fn = maybe_enter_jit - can_inline = self.state.can_inline_greenargs + can_inline = state.can_inline_greenargs + num_green_args = jd.num_green_args def maybe_enter_from_start(*args): - if can_inline is not None and not can_inline(*args[:self.num_green_args]): + if can_inline is not None and not can_inline(*args[:num_green_args]): maybe_compile_and_run(*args) maybe_enter_from_start._always_inline_ = True - self.maybe_enter_from_start_fn = maybe_enter_from_start - + jd._maybe_enter_from_start_fn = maybe_enter_from_start + def make_driverhook_graphs(self): from pypy.rlib.jit import BaseJitCell bk = self.rtyper.annotator.bookkeeper @@ -378,22 +417,23 @@ s_Str = annmodel.SomeString() # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) - self.set_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.set_jitcell_at, annmodel.s_None, - s_BaseJitCell_not_None) - self.get_jitcell_at_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) - self.can_inline_ptr = self._make_hook_graph( - annhelper, self.jitdriver.can_inline, annmodel.s_Bool) - self.get_printable_location_ptr = self._make_hook_graph( - annhelper, self.jitdriver.get_printable_location, s_Str) - self.confirm_enter_jit_ptr = self._make_hook_graph( - annhelper, self.jitdriver.confirm_enter_jit, annmodel.s_Bool, - onlygreens=False) + for jd in self.jitdrivers_sd: + jd._set_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.set_jitcell_at, annmodel.s_None, + s_BaseJitCell_not_None) + jd._get_jitcell_at_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_jitcell_at, s_BaseJitCell_or_None) + jd._can_inline_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.can_inline, annmodel.s_Bool) + jd._get_printable_location_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_printable_location, s_Str) + jd._confirm_enter_jit_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, + onlygreens=False) annhelper.finish() - def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None, - onlygreens=True): + def _make_hook_graph(self, jitdriver_sd, annhelper, func, + s_result, s_first_arg=None, onlygreens=True): if func is None: return None # @@ -401,38 +441,57 @@ if s_first_arg is not None: extra_args_s.append(s_first_arg) # - args_s = self.portal_args_s + args_s = jitdriver_sd._portal_args_s if onlygreens: - args_s = args_s[:len(self.green_args_spec)] + args_s = args_s[:len(jitdriver_sd._green_args_spec)] graph = annhelper.getgraph(func, extra_args_s + args_s, s_result) funcptr = annhelper.graph2delayed(graph) return funcptr - def make_args_specification(self): - graph, block, index = self.jit_merge_point_pos + def make_args_specifications(self): + for jd in self.jitdrivers_sd: + self.make_args_specification(jd) + + def make_args_specification(self, jd): + graph, block, index = jd._jit_merge_point_pos op = block.operations[index] greens_v, reds_v = support.decode_hp_hint_args(op) ALLARGS = [v.concretetype for v in (greens_v + reds_v)] - self.green_args_spec = [v.concretetype for v in greens_v] - self.red_args_types = [history.getkind(v.concretetype) for v in reds_v] - self.num_green_args = len(self.green_args_spec) + jd._green_args_spec = [v.concretetype for v in greens_v] + jd._red_args_types = [history.getkind(v.concretetype) for v in reds_v] + jd.num_green_args = len(jd._green_args_spec) RESTYPE = graph.getreturnvar().concretetype - (self.JIT_ENTER_FUNCTYPE, - self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) - (self.PORTAL_FUNCTYPE, - self.PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) - (_, self.PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( + (jd._JIT_ENTER_FUNCTYPE, + jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void) + (jd._PORTAL_FUNCTYPE, + jd._PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE) + (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType( [lltype.Signed, llmemory.GCREF], RESTYPE) - def rewrite_can_enter_jit(self): - FUNC = self.JIT_ENTER_FUNCTYPE - FUNCPTR = self.PTR_JIT_ENTER_FUNCTYPE - jit_enter_fnptr = self.helper_func(FUNCPTR, self.maybe_enter_jit_fn) + def rewrite_can_enter_jits(self): + can_enter_jits = find_can_enter_jit(self.translator.graphs) + sublists = {} + for jd in self.jitdrivers_sd: + sublists[jd.jitdriver] = [] + for graph, block, index in can_enter_jits: + op = block.operations[index] + jitdriver = op.args[1].value + assert jitdriver in sublists, \ + "can_enter_jit with no matching jit_merge_point" + sublists[jitdriver].append((graph, block, index)) + for jd in self.jitdrivers_sd: + sublist = sublists[jd.jitdriver] + assert len(sublist) > 0, \ + "found no can_enter_jit for %r" % (jd.jitdriver,) + self.rewrite_can_enter_jit(jd, sublist) + + def rewrite_can_enter_jit(self, jd, can_enter_jits): + FUNC = jd._JIT_ENTER_FUNCTYPE + FUNCPTR = jd._PTR_JIT_ENTER_FUNCTYPE + jit_enter_fnptr = self.helper_func(FUNCPTR, jd._maybe_enter_jit_fn) - graphs = self.translator.graphs - can_enter_jits = find_can_enter_jit(graphs) for graph, block, index in can_enter_jits: - if graph is self.jit_merge_point_pos[0]: + if graph is jd._jit_merge_point_pos[0]: continue op = block.operations[index] @@ -455,7 +514,11 @@ graph = self.annhelper.getgraph(func, args_s, s_result) return self.annhelper.graph2delayed(graph, FUNC) - def rewrite_jit_merge_point(self, policy): + def rewrite_jit_merge_points(self, policy): + for jd in self.jitdrivers_sd: + self.rewrite_jit_merge_point(jd, policy) + + def rewrite_jit_merge_point(self, jd, policy): # # Mutate the original portal graph from this: # @@ -486,9 +549,9 @@ # while 1: # more stuff # - origportalgraph = self.jit_merge_point_pos[0] - portalgraph = self.portal_graph - PORTALFUNC = self.PORTAL_FUNCTYPE + origportalgraph = jd._jit_merge_point_pos[0] + portalgraph = jd.portal_graph + PORTALFUNC = jd._PORTAL_FUNCTYPE # ____________________________________________________________ # Prepare the portal_runner() helper @@ -496,12 +559,12 @@ from pypy.jit.metainterp.warmstate import specialize_value portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal', graph = portalgraph) - self.portal_ptr = portal_ptr + jd._portal_ptr = portal_ptr # portalfunc_ARGS = [] nums = {} for i, ARG in enumerate(PORTALFUNC.ARGS): - if i < len(self.jitdriver.greens): + if i < len(jd.jitdriver.greens): color = 'green' else: color = 'red' @@ -519,7 +582,7 @@ def ll_portal_runner(*args): while 1: try: - self.maybe_enter_from_start_fn(*args) + jd._maybe_enter_from_start_fn(*args) return support.maybe_on_top_of_llinterp(rtyper, portal_ptr)(*args) except self.ContinueRunningNormally, e: @@ -548,27 +611,26 @@ value = cast_base_ptr_to_instance(Exception, value) raise Exception, value - self.ll_portal_runner = ll_portal_runner # for debugging - self.portal_runner_ptr = self.helper_func(self.PTR_PORTAL_FUNCTYPE, - ll_portal_runner) + jd._ll_portal_runner = ll_portal_runner # for debugging + jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE, + ll_portal_runner) + jd.portal_runner_adr = llmemory.cast_ptr_to_adr(jd.portal_runner_ptr) self.cpu.portal_calldescr = self.cpu.calldescrof( - self.PTR_PORTAL_FUNCTYPE.TO, - self.PTR_PORTAL_FUNCTYPE.TO.ARGS, - self.PTR_PORTAL_FUNCTYPE.TO.RESULT) - self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr) + jd._PTR_PORTAL_FUNCTYPE.TO, + jd._PTR_PORTAL_FUNCTYPE.TO.ARGS, + jd._PTR_PORTAL_FUNCTYPE.TO.RESULT) - vinfo = self.virtualizable_info + vinfo = jd.virtualizable_info def assembler_call_helper(failindex, virtualizableref): fail_descr = self.cpu.get_fail_descr_from_number(failindex) while True: + if vinfo is not None: + virtualizable = lltype.cast_opaque_ptr( + vinfo.VTYPEPTR, virtualizableref) + vinfo.reset_vable_token(virtualizable) try: - if vinfo is not None: - virtualizable = lltype.cast_opaque_ptr( - vinfo.VTYPEPTR, virtualizableref) - vinfo.reset_vable_token(virtualizable) - loop_token = fail_descr.handle_fail(self.metainterp_sd) - fail_descr = self.cpu.execute_token(loop_token) + loop_token = fail_descr.handle_fail(self.metainterp_sd, jd) except self.ContinueRunningNormally, e: args = () for ARGTYPE, attrname, count in portalfunc_ARGS: @@ -595,29 +657,26 @@ else: value = cast_base_ptr_to_instance(Exception, value) raise Exception, value + fail_descr = self.cpu.execute_token(loop_token) - self.assembler_call_helper = assembler_call_helper # for debugging - self.cpu.assembler_helper_ptr = self.helper_func( - self.PTR_ASSEMBLER_HELPER_FUNCTYPE, + jd._assembler_call_helper = assembler_call_helper # for debugging + jd._assembler_helper_ptr = self.helper_func( + jd._PTR_ASSEMBLER_HELPER_FUNCTYPE, assembler_call_helper) - # XXX a bit ugly sticking + jd.assembler_helper_adr = llmemory.cast_ptr_to_adr( + jd._assembler_helper_ptr) if vinfo is not None: - self.cpu.index_of_virtualizable = (vinfo.index_of_virtualizable - - self.num_green_args) - self.cpu.vable_token_descr = vinfo.vable_token_descr - else: - self.cpu.index_of_virtualizable = -1 - self.cpu.vable_token_descr = None + jd.vable_token_descr = vinfo.vable_token_descr # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr # - _, origblock, origindex = self.jit_merge_point_pos + _, origblock, origindex = jd._jit_merge_point_pos op = origblock.operations[origindex] assert op.opname == 'jit_marker' assert op.args[0].value == 'jit_merge_point' greens_v, reds_v = support.decode_hp_hint_args(op) - vlist = [Constant(self.portal_runner_ptr, self.PTR_PORTAL_FUNCTYPE)] + vlist = [Constant(jd.portal_runner_ptr, jd._PTR_PORTAL_FUNCTYPE)] vlist += greens_v vlist += reds_v v_result = Variable() @@ -627,6 +686,18 @@ origblock.operations.append(newop) origblock.exitswitch = None origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) + # + # Also kill any can_enter_jit left behind (example: see + # test_jitdriver.test_simple, which has a can_enter_jit in + # loop1's origportalgraph) + can_enter_jits = _find_jit_marker([origportalgraph], 'can_enter_jit') + for _, block, i in can_enter_jits: + op = block.operations[i] + assert op.opname == 'jit_marker' + block.operations[i] = SpaceOperation('same_as', + [Constant(None, lltype.Void)], + op.result) + # checkgraph(origportalgraph) def add_finish(self): @@ -644,8 +715,8 @@ graphs = self.translator.graphs _, PTR_SET_PARAM_FUNCTYPE = self.cpu.ts.get_FuncType([lltype.Signed], lltype.Void) - def make_closure(fullfuncname): - state = self.state + def make_closure(jd, fullfuncname): + state = jd.warmstate def closure(i): getattr(state, fullfuncname)(i) funcptr = self.helper_func(PTR_SET_PARAM_FUNCTYPE, closure) @@ -653,12 +724,17 @@ # for graph, block, i in find_set_param(graphs): op = block.operations[i] - assert op.args[1].value == self.jitdriver + for jd in self.jitdrivers_sd: + if jd.jitdriver is op.args[1].value: + break + else: + assert 0, "jitdriver of set_param() not found" funcname = op.args[2].value - if funcname not in closures: - closures[funcname] = make_closure('set_param_' + funcname) + key = jd, funcname + if key not in closures: + closures[key] = make_closure(jd, 'set_param_' + funcname) op.opname = 'direct_call' - op.args[:3] = [closures[funcname]] + op.args[:3] = [closures[key]] def rewrite_force_virtual(self, vrefinfo): if self.cpu.ts.name != 'lltype': Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmstate.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmstate.py Tue Jun 29 16:48:45 2010 @@ -1,7 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.rpython.ootypesystem import ootype -from pypy.rpython.annlowlevel import hlstr, cast_base_ptr_to_instance +from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance from pypy.rpython.annlowlevel import cast_object_to_ptr from pypy.rlib.objectmodel import specialize, we_are_translated, r_dict from pypy.rlib.rarithmetic import intmask @@ -120,6 +120,16 @@ else: assert False +class JitCell(BaseJitCell): + # the counter can mean the following things: + # counter >= 0: not yet traced, wait till threshold is reached + # counter == -1: there is an entry bridge for this cell + # counter == -2: tracing is currently going on for this cell + counter = 0 + compiled_merge_points = None + dont_trace_here = False + entry_loop_token = None + # ____________________________________________________________ @@ -127,9 +137,10 @@ THRESHOLD_LIMIT = sys.maxint // 2 default_jitcell_dict = None - def __init__(self, warmrunnerdesc): + def __init__(self, warmrunnerdesc, jitdriver_sd): "NOT_RPYTHON" self.warmrunnerdesc = warmrunnerdesc + self.jitdriver_sd = jitdriver_sd try: self.profiler = warmrunnerdesc.metainterp_sd.profiler except AttributeError: # for tests @@ -176,8 +187,7 @@ cell = self.jit_cell_at_key(greenkey) cell.dont_trace_here = True debug_start("jit-disableinlining") - sd = self.warmrunnerdesc.metainterp_sd - loc = sd.state.get_location_str(greenkey) + loc = self.get_location_str(greenkey) debug_print("disabled inlining", loc) debug_stop("jit-disableinlining") @@ -195,8 +205,10 @@ return self.maybe_compile_and_run metainterp_sd = self.warmrunnerdesc.metainterp_sd - vinfo = self.warmrunnerdesc.virtualizable_info - num_green_args = self.warmrunnerdesc.num_green_args + jitdriver_sd = self.jitdriver_sd + vinfo = jitdriver_sd.virtualizable_info + index_of_virtualizable = jitdriver_sd.index_of_virtualizable + num_green_args = jitdriver_sd.num_green_args get_jitcell = self.make_jitcell_getter() set_future_values = self.make_set_future_values() self.make_jitdriver_callbacks() @@ -206,7 +218,6 @@ """Entry point to the JIT. Called at the point with the can_enter_jit() hint. """ - globaldata = metainterp_sd.globaldata if NonConstant(False): # make sure we always see the saner optimizer from an # annotation point of view, otherwise we get lots of @@ -214,7 +225,7 @@ self.set_param_optimizer(OPTIMIZER_FULL) if vinfo is not None: - virtualizable = args[vinfo.index_of_virtualizable] + virtualizable = args[num_green_args + index_of_virtualizable] virtualizable = vinfo.cast_to_vtype(virtualizable) else: virtualizable = None @@ -234,11 +245,12 @@ return # bound reached; start tracing from pypy.jit.metainterp.pyjitpl import MetaInterp - metainterp = MetaInterp(metainterp_sd) + metainterp = MetaInterp(metainterp_sd, jitdriver_sd) # set counter to -2, to mean "tracing in effect" cell.counter = -2 try: - loop_token = metainterp.compile_and_run_once(*args) + loop_token = metainterp.compile_and_run_once(jitdriver_sd, + *args) finally: if cell.counter == -2: cell.counter = 0 @@ -264,7 +276,8 @@ metainterp_sd.profiler.end_running() if vinfo is not None: vinfo.reset_vable_token(virtualizable) - loop_token = fail_descr.handle_fail(metainterp_sd) + loop_token = fail_descr.handle_fail(metainterp_sd, + jitdriver_sd) maybe_compile_and_run._dont_inline_ = True self.maybe_compile_and_run = maybe_compile_and_run @@ -277,8 +290,8 @@ if hasattr(self, 'unwrap_greenkey'): return self.unwrap_greenkey # - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def unwrap_greenkey(greenkey): greenargs = () @@ -302,20 +315,10 @@ if hasattr(self, 'jit_getter'): return self.jit_getter # - class JitCell(BaseJitCell): - # the counter can mean the following things: - # counter >= 0: not yet traced, wait till threshold is reached - # counter == -1: there is an entry bridge for this cell - # counter == -2: tracing is currently going on for this cell - counter = 0 - compiled_merge_points = None - dont_trace_here = False - entry_loop_token = None - # - if self.warmrunnerdesc.get_jitcell_at_ptr is None: - jit_getter = self._make_jitcell_getter_default(JitCell) + if self.jitdriver_sd._get_jitcell_at_ptr is None: + jit_getter = self._make_jitcell_getter_default() else: - jit_getter = self._make_jitcell_getter_custom(JitCell) + jit_getter = self._make_jitcell_getter_custom() # unwrap_greenkey = self.make_unwrap_greenkey() # @@ -327,10 +330,10 @@ # return jit_getter - def _make_jitcell_getter_default(self, JitCell): + def _make_jitcell_getter_default(self): "NOT_RPYTHON" - warmrunnerdesc = self.warmrunnerdesc - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + jitdriver_sd = self.jitdriver_sd + green_args_spec = unrolling_iterable(jitdriver_sd._green_args_spec) # def comparekey(greenargs1, greenargs2): i = 0 @@ -361,11 +364,11 @@ return cell return get_jitcell - def _make_jitcell_getter_custom(self, JitCell): + def _make_jitcell_getter_custom(self): "NOT_RPYTHON" rtyper = self.warmrunnerdesc.rtyper - get_jitcell_at_ptr = self.warmrunnerdesc.get_jitcell_at_ptr - set_jitcell_at_ptr = self.warmrunnerdesc.set_jitcell_at_ptr + get_jitcell_at_ptr = self.jitdriver_sd._get_jitcell_at_ptr + set_jitcell_at_ptr = self.jitdriver_sd._set_jitcell_at_ptr lltohlhack = {} # def get_jitcell(*greenargs): @@ -415,9 +418,10 @@ return self.set_future_values warmrunnerdesc = self.warmrunnerdesc + jitdriver_sd = self.jitdriver_sd cpu = warmrunnerdesc.cpu - vinfo = warmrunnerdesc.virtualizable_info - red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) + vinfo = jitdriver_sd.virtualizable_info + red_args_types = unrolling_iterable(jitdriver_sd._red_args_types) # def set_future_values(*redargs): i = 0 @@ -428,8 +432,9 @@ set_future_values_from_vinfo(*redargs) # if vinfo is not None: - i0 = len(warmrunnerdesc.red_args_types) - num_green_args = warmrunnerdesc.num_green_args + i0 = len(jitdriver_sd._red_args_types) + num_green_args = jitdriver_sd.num_green_args + index_of_virtualizable = jitdriver_sd.index_of_virtualizable vable_static_fields = unrolling_iterable( zip(vinfo.static_extra_types, vinfo.static_fields)) vable_array_fields = unrolling_iterable( @@ -439,8 +444,7 @@ # def set_future_values_from_vinfo(*redargs): i = i0 - virtualizable = redargs[vinfo.index_of_virtualizable - - num_green_args] + virtualizable = redargs[index_of_virtualizable] virtualizable = vinfo.cast_to_vtype(virtualizable) for typecode, fieldname in vable_static_fields: x = getattr(virtualizable, fieldname) @@ -464,8 +468,9 @@ if hasattr(self, 'get_location_str'): return # - can_inline_ptr = self.warmrunnerdesc.can_inline_ptr + can_inline_ptr = self.jitdriver_sd._can_inline_ptr unwrap_greenkey = self.make_unwrap_greenkey() + jit_getter = self.make_jitcell_getter() if can_inline_ptr is None: def can_inline_callable(*greenargs): # XXX shouldn't it be False by default? @@ -477,7 +482,7 @@ fn = support.maybe_on_top_of_llinterp(rtyper, can_inline_ptr) return fn(*greenargs) def can_inline(*greenargs): - cell = self.jit_getter(*greenargs) + cell = jit_getter(*greenargs) if cell.dont_trace_here: return False return can_inline_callable(*greenargs) @@ -486,21 +491,25 @@ greenargs = unwrap_greenkey(greenkey) return can_inline(*greenargs) self.can_inline_callable = can_inline_greenkey - - get_jitcell = self.make_jitcell_getter() + def get_assembler_token(greenkey): greenargs = unwrap_greenkey(greenkey) - cell = get_jitcell(*greenargs) + cell = jit_getter(*greenargs) if cell.counter >= 0: return None return cell.entry_loop_token self.get_assembler_token = get_assembler_token # - get_location_ptr = self.warmrunnerdesc.get_printable_location_ptr + get_location_ptr = self.jitdriver_sd._get_printable_location_ptr if get_location_ptr is None: + missing = '(no jitdriver.get_printable_location!)' + missingll = llstr(missing) def get_location_str(greenkey): - return '(no jitdriver.get_printable_location!)' + if we_are_translated(): + return missingll + else: + return missing else: rtyper = self.warmrunnerdesc.rtyper unwrap_greenkey = self.make_unwrap_greenkey() @@ -514,7 +523,7 @@ return res self.get_location_str = get_location_str # - confirm_enter_jit_ptr = self.warmrunnerdesc.confirm_enter_jit_ptr + confirm_enter_jit_ptr = self.jitdriver_sd._confirm_enter_jit_ptr if confirm_enter_jit_ptr is None: def confirm_enter_jit(*args): return True Modified: pypy/trunk/pypy/jit/tl/spli/targetspli.py ============================================================================== --- pypy/trunk/pypy/jit/tl/spli/targetspli.py (original) +++ pypy/trunk/pypy/jit/tl/spli/targetspli.py Tue Jun 29 16:48:45 2010 @@ -31,7 +31,7 @@ def jitpolicy(driver): """Returns the JIT policy to use when translating.""" - from pypy.jit.metainterp.policy import JitPolicy + from pypy.jit.codewriter.policy import JitPolicy return JitPolicy() if __name__ == '__main__': Modified: pypy/trunk/pypy/jit/tl/targettlc.py ============================================================================== --- pypy/trunk/pypy/jit/tl/targettlc.py (original) +++ pypy/trunk/pypy/jit/tl/targettlc.py Tue Jun 29 16:48:45 2010 @@ -2,7 +2,7 @@ import py py.path.local(__file__) from pypy.jit.tl.tlc import interp, interp_nonjit, ConstantPool -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy from pypy.jit.backend.hlinfo import highleveljitinfo Modified: pypy/trunk/pypy/jit/tl/targettlr.py ============================================================================== --- pypy/trunk/pypy/jit/tl/targettlr.py (original) +++ pypy/trunk/pypy/jit/tl/targettlr.py Tue Jun 29 16:48:45 2010 @@ -33,7 +33,7 @@ # ____________________________________________________________ -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/trunk/pypy/jit/tl/tinyframe/targettinyframe.py ============================================================================== --- pypy/trunk/pypy/jit/tl/tinyframe/targettinyframe.py (original) +++ pypy/trunk/pypy/jit/tl/tinyframe/targettinyframe.py Tue Jun 29 16:48:45 2010 @@ -1,6 +1,6 @@ from pypy.jit.tl.tinyframe.tinyframe import main -from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.codewriter.policy import JitPolicy def jitpolicy(driver): return JitPolicy() Modified: pypy/trunk/pypy/module/__builtin__/functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/functional.py Tue Jun 29 16:48:45 2010 @@ -176,10 +176,75 @@ if not collections_w: msg = "map() requires at least two arguments" raise OperationError(space.w_TypeError, space.wrap(msg)) - num_collections = len(collections_w) none_func = space.is_w(w_func, space.w_None) - if none_func and num_collections == 1: - return space.call_function(space.w_list, collections_w[0]) + if len(collections_w) == 1: + w_collection = collections_w[0] + if none_func: + result_w = space.unpackiterable(w_collection) + else: + result_w = map_single_collection(space, w_func, w_collection) + else: + result_w = map_multiple_collections(space, w_func, collections_w, + none_func) + return space.newlist(result_w) +map.unwrap_spec = [ObjSpace, W_Root, "args_w"] + +def map_single_collection(space, w_func, w_collection): + """Special case for 'map(func, coll)', where 'func' is not None and there + is only one 'coll' argument.""" + w_iter = space.iter(w_collection) + # xxx special hacks for speed + from pypy.interpreter import function, pycode + if isinstance(w_func, function.Function): + # xxx compatibility issue: what if func_code is modified in the + # middle of running map()?? That's far too obscure for me to care... + code = w_func.getcode() + fast_natural_arity = code.fast_natural_arity + if fast_natural_arity == (1|pycode.PyCode.FLATPYCALL): + assert isinstance(code, pycode.PyCode) + return map_single_user_function(code, w_func, w_iter) + # /xxx end of special hacks + return map_single_other_callable(space, w_func, w_iter) + +def map_single_other_callable(space, w_func, w_iter): + result_w = [] + while True: + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + result_w.append(space.call_function(w_func, w_item)) + return result_w +map_single_other_callable._dont_inline_ = True + +from pypy.rlib.jit import JitDriver +mapjitdriver = JitDriver(greens = ['code'], + reds = ['w_func', 'w_iter', 'result_w'], + can_inline = lambda *args: False) +def map_single_user_function(code, w_func, w_iter): + result_w = [] + while True: + mapjitdriver.can_enter_jit(code=code, w_func=w_func, + w_iter=w_iter, result_w=result_w) + mapjitdriver.jit_merge_point(code=code, w_func=w_func, + w_iter=w_iter, result_w=result_w) + space = w_func.space + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + new_frame = space.createframe(code, w_func.w_func_globals, + w_func.closure) + new_frame.fastlocals_w[0] = w_item + w_res = new_frame.run() + result_w.append(w_res) + return result_w + +def map_multiple_collections(space, w_func, collections_w, none_func): result_w = [] iterators_w = [space.iter(w_seq) for w_seq in collections_w] num_iterators = len(iterators_w) @@ -196,16 +261,15 @@ iterators_w[i] = None else: cont = True - if cont: - w_args = space.newtuple(args_w) - if none_func: - result_w.append(w_args) - else: - w_res = space.call(w_func, w_args) - result_w.append(w_res) + if not cont: + break + w_args = space.newtuple(args_w) + if none_func: + w_res = w_args else: - return space.newlist(result_w) -map.unwrap_spec = [ObjSpace, W_Root, "args_w"] + w_res = space.call(w_func, w_args) + result_w.append(w_res) + return result_w def sum(space, w_sequence, w_start=None): if space.is_w(w_start, space.w_None): Modified: pypy/trunk/pypy/module/__builtin__/test/test_functional.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_functional.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_functional.py Tue Jun 29 16:48:45 2010 @@ -6,6 +6,9 @@ def test_trivial_map_one_seq(self): assert map(lambda x: x+2, [1, 2, 3, 4]) == [3, 4, 5, 6] + def test_trivial_map_one_seq_2(self): + assert map(str, [1, 2, 3, 4]) == ['1', '2', '3', '4'] + def test_trivial_map_two_seq(self): assert map(lambda x,y: x+y, [1, 2, 3, 4],[1, 2, 3, 4]) == ( From arigo at codespeak.net Tue Jun 29 16:50:08 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 29 Jun 2010 16:50:08 +0200 (CEST) Subject: [pypy-svn] r75663 - pypy/branch/multijit-4 Message-ID: <20100629145008.7B7C1282BDE@codespeak.net> Author: arigo Date: Tue Jun 29 16:50:07 2010 New Revision: 75663 Removed: pypy/branch/multijit-4/ Log: Remove the merged branch. Note that I did not merge the parts about playing with rlib.rsre. Might be fished from here later if needed. From arigo at codespeak.net Tue Jun 29 17:07:36 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 29 Jun 2010 17:07:36 +0200 (CEST) Subject: [pypy-svn] r75664 - pypy/trunk/pypy/jit/backend/test Message-ID: <20100629150736.7CA99282BDE@codespeak.net> Author: arigo Date: Tue Jun 29 17:07:34 2010 New Revision: 75664 Modified: pypy/trunk/pypy/jit/backend/test/support.py Log: Fix for x86/test/test_ztranslation. Modified: pypy/trunk/pypy/jit/backend/test/support.py ============================================================================== --- pypy/trunk/pypy/jit/backend/test/support.py (original) +++ pypy/trunk/pypy/jit/backend/test/support.py Tue Jun 29 17:07:34 2010 @@ -62,11 +62,12 @@ warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True, CPUClass=self.CPUClass, **kwds) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests - warmrunnerdesc.state.set_param_trace_limit(trace_limit) - warmrunnerdesc.state.set_param_inlining(inline) - warmrunnerdesc.state.set_param_optimizer(OPTIMIZER_FULL) + for jd in warmrunnerdesc.jitdrivers_sd: + jd.warmstate.set_param_threshold(3) # for tests + jd.warmstate.set_param_trace_eagerness(2) # for tests + jd.warmstate.set_param_trace_limit(trace_limit) + jd.warmstate.set_param_inlining(inline) + jd.warmstate.set_param_optimizer(OPTIMIZER_FULL) mixlevelann = warmrunnerdesc.annhelper entry_point_graph = mixlevelann.getgraph(entry_point, [s_list_of_strings], annmodel.SomeInteger()) From afa at codespeak.net Tue Jun 29 17:46:52 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 17:46:52 +0200 (CEST) Subject: [pypy-svn] r75665 - in pypy/branch/interplevel-codecs/pypy: interpreter interpreter/pyparser module/_codecs objspace/std Message-ID: <20100629154652.A7B55282BDE@codespeak.net> Author: afa Date: Tue Jun 29 17:46:51 2010 New Revision: 75665 Modified: pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py pypy/branch/interplevel-codecs/pypy/interpreter/unicodehelper.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py pypy/branch/interplevel-codecs/pypy/objspace/std/marshal_impl.py Log: Simplify interpreter/unicodehelper.py, now it calls functions in interp_codecs, and avoids applevel code. rlib.runicode can't be used directly, we need app-level exceptions. Modified: pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py Tue Jun 29 17:46:51 2010 @@ -72,12 +72,12 @@ bufp = 0 bufq = len(buf) assert 0 <= bufp <= bufq - w_substr = space.wrap(buf[bufp : bufq]) + substr = buf[bufp:bufq] if rawmode: - w_v = unicodehelper.PyUnicode_DecodeRawUnicodeEscape(space, w_substr) + v = unicodehelper.PyUnicode_DecodeRawUnicodeEscape(space, substr) else: - w_v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, w_substr) - return w_v + v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, substr) + return space.wrap(v) need_encoding = (encoding is not None and encoding != "utf-8" and encoding != "iso-8859-1") @@ -86,7 +86,7 @@ substr = s[ps : q] if rawmode or '\\' not in s[ps:]: if need_encoding: - w_u = unicodehelper.PyUnicode_DecodeUTF8(space, space.wrap(substr)) + w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, substr)) #w_v = space.wrap(space.unwrap(w_u).encode(encoding)) this works w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) return w_v @@ -200,7 +200,7 @@ # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: ps += 1 - w_u = unicodehelper.PyUnicode_DecodeUTF8(space, space.wrap(s[pt : ps])) + w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, s[pt:ps])) w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) v = space.str_w(w_v) return v, ps Modified: pypy/branch/interplevel-codecs/pypy/interpreter/unicodehelper.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/interpreter/unicodehelper.py (original) +++ pypy/branch/interplevel-codecs/pypy/interpreter/unicodehelper.py Tue Jun 29 17:46:51 2010 @@ -1,30 +1,10 @@ -from pypy.interpreter import gateway +from pypy.module._codecs import interp_codecs -app = gateway.applevel(r''' - def PyUnicode_DecodeUnicodeEscape(data): - import _codecs - return _codecs.unicode_escape_decode(data)[0] +def PyUnicode_AsEncodedString(space, w_data, w_encoding): + return interp_codecs.encode(space, w_data, w_encoding) - def PyUnicode_DecodeRawUnicodeEscape(data): - import _codecs - return _codecs.raw_unicode_escape_decode(data)[0] - - def PyUnicode_DecodeUTF8(data): - import _codecs - return _codecs.utf_8_decode(data)[0] - - def PyUnicode_AsEncodedString(data, encoding): - import _codecs - return _codecs.encode(data, encoding) - - def PyUnicode_EncodeUTF8(data): - import _codecs - return _codecs.utf_8_encode(data)[0] - -''') - -PyUnicode_DecodeUnicodeEscape = app.interphook('PyUnicode_DecodeUnicodeEscape') -PyUnicode_DecodeRawUnicodeEscape = app.interphook('PyUnicode_DecodeRawUnicodeEscape') -PyUnicode_DecodeUTF8 = app.interphook('PyUnicode_DecodeUTF8') -PyUnicode_AsEncodedString = app.interphook('PyUnicode_AsEncodedString') -PyUnicode_EncodeUTF8 = app.interphook('PyUnicode_EncodeUTF8') +# These functions take and return unwrapped rpython strings and unicodes +PyUnicode_DecodeUnicodeEscape = interp_codecs.make_raw_decoder('unicode_escape') +PyUnicode_DecodeRawUnicodeEscape = interp_codecs.make_raw_decoder('raw_unicode_escape') +PyUnicode_DecodeUTF8 = interp_codecs.make_raw_decoder('utf_8') +PyUnicode_EncodeUTF8 = interp_codecs.make_raw_encoder('utf_8') Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 17:46:51 2010 @@ -339,6 +339,31 @@ from pypy.rlib import runicode +def make_raw_encoder(name): + rname = "unicode_encode_%s" % (name.replace("_encode", ""), ) + assert hasattr(runicode, rname) + def raw_encoder(space, uni): + state = space.fromcache(CodecState) + func = getattr(runicode, rname) + errors = "strict" + return func(uni, len(uni), errors, state.encode_error_handler) + raw_encoder.func_name = rname + return raw_encoder + +def make_raw_decoder(name): + rname = "str_decode_%s" % (name.replace("_decode", ""), ) + assert hasattr(runicode, rname) + def raw_decoder(space, string): + final = True + errors = "strict" + state = space.fromcache(CodecState) + func = getattr(runicode, rname) + result, consumed = func(string, len(string), errors, + final, state.decode_error_handler) + return result + raw_decoder.func_name = rname + return raw_decoder + def make_encoder_wrapper(name): rname = "unicode_encode_%s" % (name.replace("_encode", ""), ) assert hasattr(runicode, rname) Modified: pypy/branch/interplevel-codecs/pypy/objspace/std/marshal_impl.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/objspace/std/marshal_impl.py (original) +++ pypy/branch/interplevel-codecs/pypy/objspace/std/marshal_impl.py Tue Jun 29 17:46:51 2010 @@ -447,11 +447,11 @@ register(TYPE_CODE, unmarshal_pycode) def marshal_w__Unicode(space, w_unicode, m): - s = space.str_w(unicodehelper.PyUnicode_EncodeUTF8(space, w_unicode)) + s = unicodehelper.PyUnicode_EncodeUTF8(space, space.unicode_w(w_unicode)) m.atom_str(TYPE_UNICODE, s) def unmarshal_Unicode(space, u, tc): - return unicodehelper.PyUnicode_DecodeUTF8(space, space.wrap(u.get_str())) + return space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, u.get_str())) register(TYPE_UNICODE, unmarshal_Unicode) app = gateway.applevel(r''' From afa at codespeak.net Tue Jun 29 18:04:26 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 29 Jun 2010 18:04:26 +0200 (CEST) Subject: [pypy-svn] r75666 - in pypy/branch/interplevel-codecs/pypy: interpreter/pyparser module/_codecs Message-ID: <20100629160426.DA90E282BDE@codespeak.net> Author: afa Date: Tue Jun 29 18:04:25 2010 New Revision: 75666 Modified: pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Log: Remove the "unicode" parameter. In CPython this code is disabled with a "#ifndef Py_USING_UNICODE" Modified: pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/branch/interplevel-codecs/pypy/interpreter/pyparser/parsestring.py Tue Jun 29 18:04:25 2010 @@ -96,7 +96,7 @@ enc = None if need_encoding: enc = encoding - v = PyString_DecodeEscape(space, substr, unicode, enc) + v = PyString_DecodeEscape(space, substr, enc) return space.wrap(v) def hexbyte(val): @@ -105,10 +105,9 @@ result = "0" + result return result -def PyString_DecodeEscape(space, s, unicode, recode_encoding): +def PyString_DecodeEscape(space, s, recode_encoding): """ - Unescape a backslash-escaped string. If unicode is non-zero, - the string is a u-literal. If recode_encoding is non-zero, + Unescape a backslash-escaped string. If recode_encoding is non-zero, the string is UTF-8 encoded and should be re-encoded in the specified encoding. """ @@ -171,9 +170,6 @@ raise_app_valueerror(space, 'invalid \\x escape') # ignored replace and ignore for now - elif unicode and (ch == 'u' or ch == 'U' or ch == 'N'): - raise_app_valueerror(space, 'Unicode escapes not legal ' - 'when Unicode disabled') else: # this was not an escape, so the backslash # has to be added, and we start over in Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Tue Jun 29 18:04:25 2010 @@ -642,5 +642,5 @@ @unwrap_spec(ObjSpace, str, str) def escape_decode(space, data, errors='strict'): from pypy.interpreter.pyparser.parsestring import PyString_DecodeEscape - result = PyString_DecodeEscape(space, data, False, None) + result = PyString_DecodeEscape(space, data, None) return space.newtuple([space.wrap(result), space.wrap(len(data))]) From jcreigh at codespeak.net Tue Jun 29 21:13:14 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Tue, 29 Jun 2010 21:13:14 +0200 (CEST) Subject: [pypy-svn] r75667 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100629191314.0F762282BDE@codespeak.net> Author: jcreigh Date: Tue Jun 29 21:12:33 2010 New Revision: 75667 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86.py Log: handle case on 64-bit where machine code blocks are more than 32-bits apart Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Tue Jun 29 21:12:33 2010 @@ -43,16 +43,30 @@ class MachineCodeBlockWrapper(object): MC_DEFAULT_SIZE = 1024*1024 - def __init__(self, bigsize, profile_agent=None): + def __init__(self, assembler, bigsize, profile_agent=None): + self.assembler = assembler self.old_mcs = [] # keepalive self.bigsize = bigsize self._mc = self._instantiate_mc() self.function_name = None self.profile_agent = profile_agent + self.reset_reserved_bytes() def _instantiate_mc(self): # hook for testing return codebuf.MachineCodeBlock(self.bigsize) + def ensure_bytes_available(self, num_bytes): + if self.bytes_free() <= (self._reserved_bytes + num_bytes): + self.make_new_mc() + + def reserve_bytes(self, num_bytes): + self.ensure_bytes_available(num_bytes) + self._reserved_bytes += num_bytes + + def reset_reserved_bytes(self): + # XXX er.... pretty random number, just to be sure + # not to write half-instruction + self._reserved_bytes = 64 def bytes_free(self): return self._mc._size - self._mc.get_relative_pos() @@ -74,12 +88,14 @@ def make_new_mc(self): new_mc = self._instantiate_mc() debug_print('[new machine code block at', new_mc.tell(), ']') - self._mc.JMP_l(new_mc.tell()) + self._mc.JMP(imm(new_mc.tell())) if self.function_name is not None: self.end_function(done=False) self.start_pos = new_mc.get_relative_pos() + self.assembler.write_pending_failure_recoveries() + self._mc.done() self.old_mcs.append(self._mc) self._mc = new_mc @@ -93,9 +109,7 @@ def _new_method(name): def method(self, *args): - # XXX er.... pretty random number, just to be sure - # not to write half-instruction - if self.bytes_free() < 64: + if self.bytes_free() < self._reserved_bytes: self.make_new_mc() getattr(self._mc, name)(*args) method.func_name = name @@ -109,11 +123,16 @@ setattr(MachineCodeBlockWrapper, name, _new_method(name)) class GuardToken(object): - def __init__(self, faildescr, failargs, fail_locs, exc): + def __init__(self, faildescr, failargs, fail_locs, exc, desc_bytes): self.faildescr = faildescr self.failargs = failargs self.fail_locs = fail_locs self.exc = exc + self.desc_bytes = desc_bytes + + def recovery_stub_size(self): + # XXX: 32 is pulled out of the air + return 32 + len(self.desc_bytes) class Assembler386(object): mc = None @@ -174,7 +193,7 @@ self.assembler_helper_adr = self.cpu.cast_ptr_to_int( self.cpu.assembler_helper_ptr) - self.mc = MachineCodeBlockWrapper(self.mc_size, self.cpu.profile_agent) + self.mc = MachineCodeBlockWrapper(self, self.mc_size, self.cpu.profile_agent) self._build_failure_recovery(False) self._build_failure_recovery(True) if self.cpu.supports_floats: @@ -244,9 +263,6 @@ regalloc = RegAlloc(self, self.cpu.translate_support_code) arglocs = regalloc.prepare_loop(inputargs, operations, looptoken) looptoken._x86_arglocs = arglocs - needed_mem = len(arglocs[0]) * 16 + 16 - if needed_mem >= self.mc.bytes_free(): - self.mc.make_new_mc() # profile support name = "Loop # %s: %s" % (looptoken.number, funcname) @@ -261,11 +277,7 @@ self._patch_stackadjust(adr_stackadjust, frame_depth+param_depth) looptoken._x86_frame_depth = frame_depth looptoken._x86_param_depth = param_depth - # we need to make sure here that we don't overload an mc badly. - # a safe estimate is that we need at most 16 bytes per arg - needed_mem = len(arglocs[0]) * 16 + 16 - if needed_mem >= self.mc.bytes_free(): - self.mc.make_new_mc() + looptoken._x86_direct_bootstrap_code = self.mc.tell() self._assemble_bootstrap_direct_call(arglocs, curadr, frame_depth+param_depth) @@ -311,10 +323,15 @@ def write_pending_failure_recoveries(self): for tok in self.pending_guard_tokens: - addr = self.generate_quick_failure(tok.faildescr, tok.failargs, tok.fail_locs, tok.exc) + # Okay to write to _mc because we've already made sure that + # there's enough space by "reserving" bytes. + addr = self.generate_quick_failure(self.mc._mc, tok.faildescr, tok.failargs, tok.fail_locs, tok.exc, tok.desc_bytes) + tok.faildescr._x86_adr_recovery_stub = addr self.patch_jump_for_descr(tok.faildescr, addr) self.pending_guard_tokens = [] + self.mc.reset_reserved_bytes() + self.mc.done() def _find_debug_merge_point(self, operations): for op in operations: @@ -324,8 +341,21 @@ def patch_jump_for_descr(self, faildescr, adr_new_target): adr_jump_offset = faildescr._x86_adr_jump_offset - mc = codebuf.InMemoryCodeBuilder(adr_jump_offset, adr_jump_offset + 4) - mc.writeimm32(adr_new_target - adr_jump_offset - 4) + adr_recovery_stub = faildescr._x86_adr_recovery_stub + offset = adr_new_target - (adr_jump_offset + 4) + # If the new target fits within a rel32 of the jump, just patch + # that. Otherwise, leave the original rel32 to the recovery stub in + # place, but clobber the recovery stub with a jump to the real + # target. + if rx86.fits_in_32bits(offset): + mc = codebuf.InMemoryCodeBuilder(adr_jump_offset, adr_jump_offset + 4) + mc.writeimm32(offset) + else: + # "mov r11, addr; jmp r11" is 13 bytes + mc = codebuf.InMemoryCodeBuilder(adr_recovery_stub, adr_recovery_stub + 13) + mc.MOV_ri(X86_64_SCRATCH_REG.value, adr_new_target) + mc.JMP_r(X86_64_SCRATCH_REG.value) + mc.valgrind_invalidated() mc.done() @@ -434,6 +464,7 @@ if len(unused_gpr) > 0: self.mc.MOV(loc, unused_gpr.pop()) else: + self.mc.ensure_bytes_available(32) self.mc.MOV_rb(X86_64_SCRATCH_REG.value, (2 + i) * WORD) self.mc.MOV(loc, X86_64_SCRATCH_REG) @@ -446,8 +477,7 @@ self.mc.MOVSD_xb(X86_64_XMM_SCRATCH_REG.value, (2 + i) * WORD) self.mc.MOVSD(loc, X86_64_XMM_SCRATCH_REG) - - self.mc.JMP_l(jmpadr) + self.mc.JMP(imm(jmpadr)) return adr_stackadjust @@ -568,7 +598,6 @@ guard_token = self.implement_guard_recovery(guard_opnum, faildescr, failargs, faillocs) - self.pending_guard_tokens.append(guard_token) if op is None: dispatch_opnum = guard_opnum else: @@ -615,6 +644,9 @@ tmp2 = result_loc.higher8bits() elif IS_X86_64: tmp2 = X86_64_SCRATCH_REG.lowest8bits() + # We can't do a jump in the middle below, because that could + # clobber the scratch register + self.mc.ensure_bytes_available(32) self.mc.SET_ir(rx86.Conditions[cond], tmp1.value) if is_ne: @@ -648,16 +680,17 @@ result_loc): guard_opnum = guard_op.opnum self.mc.UCOMISD(arglocs[0], arglocs[1]) + # 16 is enough space for the rel8 jumps below and the rel32 + # jump in implement_guard + self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size()) if guard_opnum == rop.GUARD_FALSE: - mc = self.mc._mc if need_jp: - mc.J_il8(rx86.Conditions['P'], 6) + self.mc.J_il8(rx86.Conditions['P'], 6) return self.implement_guard(guard_token, cond) else: if need_jp: - mc = self.mc._mc - mc.J_il8(rx86.Conditions['P'], 2) - mc.J_il8(rx86.Conditions[cond], 5) + self.mc.J_il8(rx86.Conditions['P'], 2) + self.mc.J_il8(rx86.Conditions[cond], 5) return self.implement_guard(guard_token) return self.implement_guard(guard_token, false_cond) return genop_cmp_guard_float @@ -734,6 +767,8 @@ mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) mc.MOVSD_sx(i*WORD, X86_64_XMM_SCRATCH_REG.value) else: + if not force_mc: + mc.ensure_bytes_available(32) mc.MOV(X86_64_SCRATCH_REG, loc) mc.MOV_sr(i*WORD, X86_64_SCRATCH_REG.value) else: @@ -847,13 +882,15 @@ def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc): guard_opnum = guard_op.opnum self.mc.UCOMISD(arglocs[0], arglocs[1]) - mc = self.mc._mc + # 16 is enough space for the rel8 jumps below and the rel32 + # jump in implement_guard + self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size()) if guard_opnum == rop.GUARD_TRUE: - mc.J_il8(rx86.Conditions['P'], 6) + self.mc.J_il8(rx86.Conditions['P'], 6) return self.implement_guard(guard_token, 'E') else: - mc.J_il8(rx86.Conditions['P'], 2) - mc.J_il8(rx86.Conditions['E'], 5) + self.mc.J_il8(rx86.Conditions['P'], 2) + self.mc.J_il8(rx86.Conditions['E'], 5) return self.implement_guard(guard_token) def genop_float_neg(self, op, arglocs, resloc): @@ -1190,9 +1227,10 @@ exc = (guard_opnum == rop.GUARD_EXCEPTION or guard_opnum == rop.GUARD_NO_EXCEPTION or guard_opnum == rop.GUARD_NOT_FORCED) - return GuardToken(faildescr, failargs, fail_locs, exc) + desc_bytes = self.failure_recovery_description(failargs, fail_locs) + return GuardToken(faildescr, failargs, fail_locs, exc, desc_bytes) - def generate_quick_failure(self, faildescr, failargs, fail_locs, exc): + def generate_quick_failure(self, mc, faildescr, failargs, fail_locs, exc, desc_bytes): """Generate the initial code for handling a failure. We try to keep it as compact as possible. The idea is that this code is executed at most once (and very often, zero times); when @@ -1200,20 +1238,17 @@ really handle recovery from this particular failure. """ fail_index = self.cpu.get_fail_descr_number(faildescr) - bytes_needed = 20 + 5 * len(failargs) # conservative estimate - if self.mc.bytes_free() < bytes_needed: - self.mc.make_new_mc() - mc = self.mc._mc addr = mc.tell() withfloats = False for box in failargs: if box is not None and box.type == FLOAT: withfloats = True break - mc.CALL_l(self.failure_recovery_code[exc + 2 * withfloats]) + mc.CALL(imm(self.failure_recovery_code[exc + 2 * withfloats])) # write tight data that describes the failure recovery faildescr._x86_failure_recovery_bytecode = mc.tell() - self.write_failure_recovery_description(mc, failargs, fail_locs) + for byte in desc_bytes: + mc.writechr(ord(byte)) # write the fail_index too mc.writeimm32(fail_index) # for testing the decoding, write a final byte 0xCC @@ -1221,6 +1256,12 @@ mc.writechr(0xCC) faildescr._x86_debug_faillocs = [loc for loc in fail_locs if loc is not None] + + # Make sure the recovery stub is at least 16 bytes long (for the + # case where we overwrite the recovery stub with a 64-bit absolute + # jump) + while mc.tell() - addr < 16: + mc.writechr(0x00) return addr DESCR_REF = 0x00 @@ -1232,7 +1273,8 @@ CODE_STOP = 0 | DESCR_SPECIAL CODE_HOLE = 4 | DESCR_SPECIAL - def write_failure_recovery_description(self, mc, failargs, locs): + def failure_recovery_description(self, failargs, locs): + desc_bytes = [] for i in range(len(failargs)): arg = failargs[i] if arg is not None: @@ -1252,14 +1294,19 @@ n = loc.value n = kind + 4*n while n > 0x7F: - mc.writechr((n & 0x7F) | 0x80) + desc_bytes.append(chr((n & 0x7F) | 0x80)) n >>= 7 else: n = self.CODE_HOLE - mc.writechr(n) - mc.writechr(self.CODE_STOP) + desc_bytes.append(chr(n)) + desc_bytes.append(chr(self.CODE_STOP)) # assert that the fail_boxes lists are big enough assert len(failargs) <= self.fail_boxes_int.SIZE + return desc_bytes + + def write_failure_recovery_description(self, mc, failargs, locs): + for byte in self.failure_recovery_description(failargs, locs): + mc.writechr(ord(byte)) def rebuild_faillocs_from_descr(self, bytecode): from pypy.jit.backend.x86.regalloc import X86FrameManager @@ -1421,7 +1468,7 @@ # avoid unwarranted freeing # - optionally save exception depending on the flag addr = self.cpu.get_on_leave_jitted_int(save_exception=exc) - mc.CALL_l(addr) + mc.CALL(imm(addr)) # the following call saves all values from the stack and from # registers to the right 'fail_boxes_' location. @@ -1442,7 +1489,7 @@ else: raise AssertionError("Shouldn't happen") - mc.CALL_l(failure_recovery_func) + mc.CALL(imm(failure_recovery_func)) # returns in eax the fail_index # now we return from the complete frame, which starts from @@ -1491,7 +1538,7 @@ # avoid unwarranted freeing # - optionally save exception depending on the flag addr = self.cpu.get_on_leave_jitted_int(save_exception=exc) - mc.CALL_l(addr) + mc.CALL(imm(addr)) mc.MOV(eax, imm(fail_index)) @@ -1502,7 +1549,10 @@ # what to do with @specialize @specialize.arg(2) def implement_guard(self, guard_token, condition=None): - # These jumps are patched later + self.mc.reserve_bytes(guard_token.recovery_stub_size()) + self.pending_guard_tokens.append(guard_token) + # XXX: These jumps are patched later, the self.mc.tell() are just + # dummy values if condition: self.mc.J_il(rx86.Conditions[condition], self.mc.tell()) else: @@ -1697,7 +1747,7 @@ return loop_token._x86_arglocs def closing_jump(self, loop_token): - self.mc.JMP_l(loop_token._x86_loop_code) + self.mc.JMP(imm(loop_token._x86_loop_code)) def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr, size, tid): @@ -1723,10 +1773,10 @@ # reserve room for the argument to the real malloc and the # 8 saved XMM regs self._regalloc.reserve_param(1+16) - mc.CALL_l(slowpath_addr1) + mc.CALL(imm(slowpath_addr1)) self.mark_gc_roots() slowpath_addr2 = self.malloc_fixedsize_slowpath2 - mc.CALL_l(slowpath_addr2) + mc.CALL(imm(slowpath_addr2)) offset = mc.get_relative_pos() - jmp_adr assert 0 < offset <= 127 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Tue Jun 29 21:12:33 2010 @@ -224,6 +224,25 @@ return func_with_new_name(INSN, "INSN_" + name) + def _relative_unaryop(name): + def INSN(self, loc): + code = loc.location_code() + for possible_code in unrolling_location_codes: + if code == possible_code: + val = getattr(loc, "value_" + possible_code)() + if self.WORD == 8 and possible_code == 'i': + offset = val - (self.tell() + 5) + if rx86.fits_in_32bits(offset): + _rx86_getattr(self, name + "_l")(val) + else: + self.MOV_ri(X86_64_SCRATCH_REG.value, val) + _rx86_getattr(self, name + "_r")(X86_64_SCRATCH_REG.value) + else: + methname = name + "_" + possible_code + _rx86_getattr(self, methname)(val) + + return func_with_new_name(INSN, "INSN_" + name) + def _16_bit_binaryop(name): def INSN(self, loc1, loc2): # Select 16-bit operand mode @@ -306,8 +325,8 @@ ANDPD = _binaryop('ANDPD') XORPD = _binaryop('XORPD') - CALL = _unaryop('CALL') - JMP = _unaryop('JMP') + CALL = _relative_unaryop('CALL') + JMP = _relative_unaryop('JMP') def imm(x): # XXX: ri386 migration shim Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Tue Jun 29 21:12:33 2010 @@ -575,17 +575,6 @@ else: AbstractX86CodeBuilder.MOV_ri(self, reg, immed) - # case of a 64-bit immediate: encode via RAX (assuming it's ok to - # randomly change this register at that point in time) - def CALL_l(self, target): - offset = target - (self.tell() + 5) - if fits_in_32bits(offset): - AbstractX86CodeBuilder.CALL_l(self, target) - else: - self.MOV_ri(R.eax, target) - self.CALL_r(R.eax) - - def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): args = before_modrm + list(modrm) + after_modrm Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_assembler.py Tue Jun 29 21:12:33 2010 @@ -26,11 +26,14 @@ return self.base_address + len(self.content) def get_relative_pos(self): return len(self.content) - def JMP_l(self, *args): + def JMP(self, *args): self.content.append(("JMP", args)) def done(self): pass +class FakeAssembler: + def write_pending_failure_recoveries(self): + pass def test_write_failure_recovery_description(): assembler = Assembler386(FakeCPU()) @@ -257,7 +260,8 @@ def test_mc_wrapper_profile_agent(): agent = FakeProfileAgent() - mc = FakeMCWrapper(100, agent) + assembler = FakeAssembler() + mc = FakeMCWrapper(assembler, 100, agent) mc.start_function("abc") mc.writechr("x") mc.writechr("x") Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Tue Jun 29 21:12:33 2010 @@ -399,8 +399,6 @@ assert self.cpu.get_latest_value_int(0) == 1024 def test_overflow_guard_float_cmp(self): - # FIXME: Skipping for now - import py.test; py.test.skip() # The float comparisons on x86 tend to use small relative jumps, # which may run into trouble if they fall on the edge of a # MachineCodeBlock change. Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_rx86.py Tue Jun 29 21:12:33 2010 @@ -208,12 +208,3 @@ s = CodeBuilder64() s.MOV_rm(edx, (edi, -1)) assert s.getvalue() == '\x48\x8B\x57\xFF' - -def test_call_l_64(): - # first check that it works there too - test_call_l(CodeBuilder64()) - # then check the other case - s = CodeBuilder64() - target = 0x0123456789ABCDEF - s.CALL_l(target) # becomes indirect, via RAX - assert s.getvalue() == '\x48\xB8' + struct.pack(" Author: afa Date: Wed Jun 30 01:26:32 2010 New Revision: 75668 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Log: Fix for unicode literals containing \N{} Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/interp_codecs.py Wed Jun 30 01:26:32 2010 @@ -14,7 +14,7 @@ self.decode_error_handler = self.make_errorhandler(space, True) self.encode_error_handler = self.make_errorhandler(space, False) - self.unicodedata_getcode = None + self.unicodedata_handler = None def make_errorhandler(self, space, decode): def unicode_call_errorhandler(errors, encoding, reason, input, @@ -56,16 +56,20 @@ return replace, newpos return unicode_call_errorhandler - def get_unicodedata_function(self, space): - if self.unicodedata_getcode: - return self.unicodedata_getcode - w_builtin = space.getbuiltinmodule('__builtin__') - w_import = space.getattr(w_builtin, space.wrap("__import__")) - w_unicodedata = space.call_function(w_import, - space.wrap("unicodedata")) - self.unicodedata_getcode = space.getattr(w_unicodedata, - space.wrap("_get_code")) - return self.unicodedata_getcode + def get_unicodedata_handler(self, space): + if self.unicodedata_handler: + return self.unicodedata_handler + try: + w_builtin = space.getbuiltinmodule('__builtin__') + w_import = space.getattr(w_builtin, space.wrap("__import__")) + w_unicodedata = space.call_function(w_import, + space.wrap("unicodedata")) + w_getcode = space.getattr(w_unicodedata, space.wrap("_get_code")) + except OperationError: + return None + else: + self.unicodedata_handler = UnicodeData_Handler(space, w_getcode) + return self.unicodedata_handler def _freeze_(self): assert not self.codec_search_path @@ -358,8 +362,15 @@ errors = "strict" state = space.fromcache(CodecState) func = getattr(runicode, rname) - result, consumed = func(string, len(string), errors, - final, state.decode_error_handler) + kwargs = {} + if name == 'unicode_escape': + unicodedata_handler = state.get_unicodedata_handler(space) + result, consumed = func(string, len(string), errors, + final, state.decode_error_handler, + unicodedata_handler=unicodedata_handler) + else: + result, consumed = func(string, len(string), errors, + final, state.decode_error_handler) return result raw_decoder.func_name = rname return raw_decoder @@ -575,15 +586,14 @@ # Unicode escape class UnicodeData_Handler: - def __init__(self, space): + def __init__(self, space, w_getcode): self.space = space - state = space.fromcache(CodecState) - self.get_code = state.get_unicodedata_function(space) + self.w_getcode = w_getcode def call(self, name): space = self.space try: - w_code = space.call_function(self.get_code, space.wrap(name)) + w_code = space.call_function(self.w_getcode, space.wrap(name)) except OperationError, e: if not e.match(space, space.w_KeyError): raise @@ -596,10 +606,7 @@ state = space.fromcache(CodecState) errorhandler=state.decode_error_handler - try: - unicode_name_handler = UnicodeData_Handler(space) - except OperationError: - unicode_name_handler = None + unicode_name_handler = state.get_unicodedata_handler(space) result, consumed = runicode.str_decode_unicode_escape( string, len(string), errors, From afa at codespeak.net Wed Jun 30 10:46:37 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 30 Jun 2010 10:46:37 +0200 (CEST) Subject: [pypy-svn] r75669 - in pypy/branch/interplevel-codecs/pypy: module/_codecs/test rlib Message-ID: <20100630084637.527D8282BE3@codespeak.net> Author: afa Date: Wed Jun 30 10:46:35 2010 New Revision: 75669 Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: use \x escape code when possible. Test and fix. Modified: pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/branch/interplevel-codecs/pypy/module/_codecs/test/test_codecs.py Wed Jun 30 10:46:35 2010 @@ -554,6 +554,7 @@ assert u'\\'.encode('unicode-escape') == '\\\\' assert '\\\\'.decode('unicode-escape') == u'\\' assert u'\ud801'.encode('unicode-escape') == '\\ud801' + assert u'\u0013'.encode('unicode-escape') == '\\x13' def test_mbcs(self): import sys Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Wed Jun 30 10:46:35 2010 @@ -1095,9 +1095,12 @@ if char >= 0x10000: result.append("\\U") zeros = 8 - else: + elif char >= 0x100: result.append("\\u") zeros = 4 + else: + result.append("\\x") + zeros = 2 nb = zeros + 2 - len(num) # num starts with '0x' if nb > 0: result.append_multiple_char('0', nb) From afa at codespeak.net Wed Jun 30 10:50:48 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 30 Jun 2010 10:50:48 +0200 (CEST) Subject: [pypy-svn] r75670 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100630085048.F2307282BEB@codespeak.net> Author: afa Date: Wed Jun 30 10:50:47 2010 New Revision: 75670 Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: remove code duplication: 'oc > 127' covers all these cases Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Wed Jun 30 10:50:47 2010 @@ -971,11 +971,6 @@ pos += 1 continue - if oc > 0x10000: - raw_unicode_escape_helper(result, oc) - pos += 1 - continue - if 0xD800 <= oc < 0xDC00 and pos + 1 < size: # Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes pos += 1 @@ -989,12 +984,6 @@ # Fall through: isolated surrogates are copied as-is pos -= 1 - # Map 16-bit characters to '\uxxxx' - if oc >= 0x100: - raw_unicode_escape_helper(result, oc) - pos += 1 - continue - # Map special whitespace to '\t', \n', '\r' if ch == '\t': result.append('\\t') @@ -1005,9 +994,10 @@ elif ch == '\\': result.append('\\\\') - # Map non-printable US ASCII to '\xhh' - elif (oc < 32 or oc >= 0x7F) : + # Map non-printable or non-ascii to '\xhh' or '\uhhhh' + elif oc < 32 or oc > 0x7F: raw_unicode_escape_helper(result, oc) + # Copy everything else as-is else: result.append(chr(oc)) From afa at codespeak.net Wed Jun 30 10:52:11 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 30 Jun 2010 10:52:11 +0200 (CEST) Subject: [pypy-svn] r75671 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100630085211.4518B282BF1@codespeak.net> Author: afa Date: Wed Jun 30 10:52:09 2010 New Revision: 75671 Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: oops, I broke a test: chr(127) prints as '\x7f' Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Wed Jun 30 10:52:09 2010 @@ -995,7 +995,7 @@ result.append('\\\\') # Map non-printable or non-ascii to '\xhh' or '\uhhhh' - elif oc < 32 or oc > 0x7F: + elif oc < 32 or oc >= 0x7F: raw_unicode_escape_helper(result, oc) # Copy everything else as-is From afa at codespeak.net Wed Jun 30 11:02:52 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 30 Jun 2010 11:02:52 +0200 (CEST) Subject: [pypy-svn] r75672 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100630090252.73371282BE3@codespeak.net> Author: afa Date: Wed Jun 30 11:02:50 2010 New Revision: 75672 Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Log: It seems that the translated version of StringBuilder.append_slice does not check for bounds Modified: pypy/branch/interplevel-codecs/pypy/rlib/runicode.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/runicode.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/runicode.py Wed Jun 30 11:02:50 2010 @@ -1091,10 +1091,11 @@ else: result.append("\\x") zeros = 2 - nb = zeros + 2 - len(num) # num starts with '0x' + lnum = len(num) + nb = zeros + 2 - lnum # num starts with '0x' if nb > 0: result.append_multiple_char('0', nb) - result.append_slice(num, 2, 8) + result.append_slice(num, 2, lnum) def unicode_encode_raw_unicode_escape(s, size, errors, errorhandler=None): # errorhandler is not used: this function cannot cause Unicode errors From afa at codespeak.net Wed Jun 30 11:09:01 2010 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 30 Jun 2010 11:09:01 +0200 (CEST) Subject: [pypy-svn] r75673 - pypy/branch/interplevel-codecs/pypy/rlib Message-ID: <20100630090901.C7720282BE3@codespeak.net> Author: afa Date: Wed Jun 30 11:09:00 2010 New Revision: 75673 Modified: pypy/branch/interplevel-codecs/pypy/rlib/rstring.py Log: This code is not translated, but this assert would have detected the out-of-bounds error fixed in the previous change. Modified: pypy/branch/interplevel-codecs/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/interplevel-codecs/pypy/rlib/rstring.py (original) +++ pypy/branch/interplevel-codecs/pypy/rlib/rstring.py Wed Jun 30 11:09:00 2010 @@ -56,6 +56,7 @@ self.l.append(s) def append_slice(self, s, start, end): + assert 0 <= start <= end <= len(s) self.l.append(s[start:end]) def append_multiple_char(self, c, times): From arigo at codespeak.net Wed Jun 30 12:50:11 2010 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Jun 2010 12:50:11 +0200 (CEST) Subject: [pypy-svn] r75675 - in pypy/trunk/pypy/rlib: . test Message-ID: <20100630105011.D851D282BE3@codespeak.net> Author: arigo Date: Wed Jun 30 12:50:10 2010 New Revision: 75675 Modified: pypy/trunk/pypy/rlib/debug.py pypy/trunk/pypy/rlib/test/test_debug.py Log: An annotation-time check: check_nonneg(). Modified: pypy/trunk/pypy/rlib/debug.py ============================================================================== --- pypy/trunk/pypy/rlib/debug.py (original) +++ pypy/trunk/pypy/rlib/debug.py Wed Jun 30 12:50:10 2010 @@ -250,3 +250,16 @@ def specialize_call(self, hop): hop.exception_cannot_occur() return hop.inputarg(hop.args_r[0], arg=0) + + +class IntegerCanBeNegative(Exception): + pass + +def _check_nonneg(ann, bk): + from pypy.annotation.model import SomeInteger + s_nonneg = SomeInteger(nonneg=True) + if not s_nonneg.contains(ann): + raise IntegerCanBeNegative + +def check_nonneg(x): + check_annotation(x, _check_nonneg) Modified: pypy/trunk/pypy/rlib/test/test_debug.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_debug.py (original) +++ pypy/trunk/pypy/rlib/test/test_debug.py Wed Jun 30 12:50:10 2010 @@ -3,6 +3,7 @@ from pypy.rlib.debug import check_annotation, make_sure_not_resized from pypy.rlib.debug import debug_print, debug_start, debug_stop from pypy.rlib.debug import have_debug_prints +from pypy.rlib.debug import check_nonneg, IntegerCanBeNegative from pypy.rlib import debug from pypy.rpython.test.test_llinterp import interpret @@ -30,6 +31,16 @@ py.test.raises(Error, "interpret(g, [3])") +def test_check_nonneg(): + def f(x): + assert x >= 5 + check_nonneg(x) + interpret(f, [9]) + + def g(x): + check_nonneg(x-1) + py.test.raises(IntegerCanBeNegative, interpret, g, [9]) + def test_make_sure_not_resized(): from pypy.annotation.listdef import TooLateForChange def f(): From hpk at codespeak.net Wed Jun 30 14:41:52 2010 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 30 Jun 2010 14:41:52 +0200 (CEST) Subject: [pypy-svn] r75676 - pypy/trunk/lib_pypy Message-ID: <20100630124152.784C8282BDE@codespeak.net> Author: hpk Date: Wed Jun 30 14:41:50 2010 New Revision: 75676 Removed: pypy/trunk/lib_pypy/py Log: removing the pylib from python's extra lib_pypy directory which should probably only contain standard library modules (backported ones and ones converted from C to python. From antocuni at codespeak.net Wed Jun 30 16:51:14 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Jun 2010 16:51:14 +0200 (CEST) Subject: [pypy-svn] r75683 - in pypy/trunk: include lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command pypy/_interfaces pypy/module/cpyext pypy/module/cpyext/test Message-ID: <20100630145114.AB57C282BE3@codespeak.net> Author: antocuni Date: Wed Jun 30 16:51:13 2010 New Revision: 75683 Added: pypy/trunk/include/ (props changed) pypy/trunk/include/README Removed: pypy/trunk/pypy/_interfaces/ Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py pypy/trunk/pypy/module/cpyext/api.py pypy/trunk/pypy/module/cpyext/test/test_api.py Log: create a directory trunk/include to contains all the headers file. They are automatically copied there from cpyext/include during translation. The generated pypy_decl.h and pypy_macros.h are also put there, instead of the now-gone pypy/_interfaces. The goal is to have the svn checkout as similar as possible as release tarballs and virtualenvs, which have an include/ dir at the top Added: pypy/trunk/include/README ============================================================================== --- (empty file) +++ pypy/trunk/include/README Wed Jun 30 16:51:13 2010 @@ -0,0 +1,7 @@ +This directory contains all the include files needed to build cpython +extensions with PyPy. Note that these are just copies of the original headers +that are in pypy/module/cpyext/include: they are automatically copied from +there during translation. + +Moreover, pypy_decl.h and pypy_macros.h are automatically generated, also +during translation. Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/command/build_ext.py Wed Jun 30 16:51:13 2010 @@ -167,7 +167,7 @@ # for Release and Debug builds. # also Python's library directory must be appended to library_dirs if os.name == 'nt': - self.library_dirs.append(os.path.join(sys.prefix, 'pypy', '_interfaces')) + self.library_dirs.append(os.path.join(sys.prefix, 'include')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Wed Jun 30 16:51:13 2010 @@ -13,12 +13,7 @@ def get_python_inc(plat_specific=0, prefix=None): from os.path import join as j - cand = j(sys.prefix, 'include') - if os.path.exists(cand): - return cand - if plat_specific: - return j(sys.prefix, "pypy", "_interfaces") - return j(sys.prefix, 'pypy', 'module', 'cpyext', 'include') + return j(sys.prefix, 'include') def get_python_version(): """Return a string containing the major and minor Python version, Modified: pypy/trunk/pypy/module/cpyext/api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/api.py (original) +++ pypy/trunk/pypy/module/cpyext/api.py Wed Jun 30 16:51:13 2010 @@ -45,11 +45,9 @@ pypydir = py.path.local(autopath.pypydir) include_dir = pypydir / 'module' / 'cpyext' / 'include' source_dir = pypydir / 'module' / 'cpyext' / 'src' -interfaces_dir = pypydir / "_interfaces" include_dirs = [ include_dir, udir, - interfaces_dir, ] class CConfig: @@ -100,9 +98,16 @@ udir.join('pypy_macros.h').write("/* Will be filled later */") globals().update(rffi_platform.configure(CConfig_constants)) -def copy_header_files(): +def copy_header_files(dstdir): + assert dstdir.check(dir=True) + headers = include_dir.listdir('*.h') + include_dir.listdir('*.inl') for name in ("pypy_decl.h", "pypy_macros.h"): - udir.join(name).copy(interfaces_dir / name) + headers.append(udir.join(name)) + for header in headers: + header.copy(dstdir) + target = dstdir.join(header.basename) + target.chmod(0444) # make the file read-only, to make sure that nobody + # edits it by mistake _NOT_SPECIFIED = object() CANNOT_FAIL = object() @@ -881,7 +886,8 @@ deco(func.get_wrapper(space)) setup_init_functions(eci) - copy_header_files() + trunk_include = pypydir.dirpath() / 'include' + copy_header_files(trunk_include) initfunctype = lltype.Ptr(lltype.FuncType([], lltype.Void)) @unwrap_spec(ObjSpace, str, str) Modified: pypy/trunk/pypy/module/cpyext/test/test_api.py ============================================================================== --- pypy/trunk/pypy/module/cpyext/test/test_api.py (original) +++ pypy/trunk/pypy/module/cpyext/test/test_api.py Wed Jun 30 16:51:13 2010 @@ -1,3 +1,4 @@ +import py from pypy.conftest import gettestobjspace from pypy.rpython.lltypesystem import rffi, lltype from pypy.interpreter.baseobjspace import W_Root @@ -68,3 +69,13 @@ api.PyPy_GetWrapped(space.w_None) api.PyPy_GetReference(space.w_None) + +def test_copy_header_files(tmpdir): + api.copy_header_files(tmpdir) + def check(name): + f = tmpdir.join(name) + assert f.check(file=True) + py.test.raises(py.error.EACCES, "f.open('w')") # check that it's not writable + check('Python.h') + check('modsupport.inl') + check('pypy_decl.h') From antocuni at codespeak.net Wed Jun 30 16:57:03 2010 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Jun 2010 16:57:03 +0200 (CEST) Subject: [pypy-svn] r75684 - in pypy/trunk/pypy/tool/release: . test Message-ID: <20100630145703.57DC6282BE3@codespeak.net> Author: antocuni Date: Wed Jun 30 16:57:01 2010 New Revision: 75684 Modified: pypy/trunk/pypy/tool/release/package.py pypy/trunk/pypy/tool/release/test/test_package.py Log: fix package.py to take the headers from trunk/include instead of fishing them here and there. Also, make sure it also copies *.inl, which were ignored before Modified: pypy/trunk/pypy/tool/release/package.py ============================================================================== --- pypy/trunk/pypy/tool/release/package.py (original) +++ pypy/trunk/pypy/tool/release/package.py Wed Jun 30 16:57:01 2010 @@ -57,11 +57,11 @@ for file in ['LICENSE', 'README']: shutil.copy(str(basedir.join(file)), str(pypydir)) pypydir.ensure('include', dir=True) - # we want to put there all *.h from module/cpyext/include + # we want to put there all *.h and *.inl from trunk/include # and from pypy/_interfaces - for n in basedir.join('pypy', 'module', 'cpyext', 'include').listdir('*.h'): - shutil.copy(str(n), str(pypydir.join('include'))) - for n in basedir.join('pypy', '_interfaces').listdir('*.h'): + includedir = basedir.join('include') + headers = includedir.listdir('*.h') + includedir.listdir('*.inl') + for n in headers: shutil.copy(str(n), str(pypydir.join('include'))) pypydir.ensure('bin', dir=True) archive_pypy_c = pypydir.join('bin', rename_pypy_c) Modified: pypy/trunk/pypy/tool/release/test/test_package.py ============================================================================== --- pypy/trunk/pypy/tool/release/test/test_package.py (original) +++ pypy/trunk/pypy/tool/release/test/test_package.py Wed Jun 30 16:57:01 2010 @@ -26,6 +26,9 @@ assert prefix.join('README').check() th = tarfile.open(str(builddir.join('test.tar.bz2'))) assert th.getmember('test/lib_pypy/syslog.py') + assert th.getmember('test/include/Python.h') + assert th.getmember('test/include/modsupport.inl') + assert th.getmember('test/include/pypy_decl.h') finally: if fake_pypy_c: pypy_c.remove() From benjamin at codespeak.net Wed Jun 30 17:13:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 17:13:09 +0200 (CEST) Subject: [pypy-svn] r75686 - in pypy/branch/fast-forward/pypy: module/__builtin__ module/__builtin__/test objspace objspace/std objspace/test Message-ID: <20100630151309.7232D282BE3@codespeak.net> Author: benjamin Date: Wed Jun 30 17:13:07 2010 New Revision: 75686 Modified: pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py pypy/branch/fast-forward/pypy/objspace/descroperation.py pypy/branch/fast-forward/pypy/objspace/std/objspace.py pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py Log: new plan: disable isinstance() and issubtype() overriding by user classes by default Modified: pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py Wed Jun 30 17:13:07 2010 @@ -45,12 +45,20 @@ return space.type(w_obj) @jit.unroll_safe -def abstract_isinstance_w(space, w_obj, w_klass_or_tuple): +def abstract_isinstance_w(space, w_obj, w_klass_or_tuple, allow_override=False): """Implementation for the full 'isinstance(obj, klass_or_tuple)'.""" + # -- case (anything, tuple) + # XXX it might be risky that the JIT sees this + if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)): + for w_klass in space.fixedview(w_klass_or_tuple): + if abstract_isinstance_w(space, w_obj, w_klass, allow_override): + return True + return False + # -- case (anything, type) try: - w_result = space.isinstance(w_obj, w_klass_or_tuple) + w_result = space.isinstance(w_obj, w_klass_or_tuple, allow_override) except OperationError, e: # if w_klass_or_tuple was not a type, ignore it if not e.match(space, space.w_TypeError): raise # propagate other errors @@ -64,7 +72,8 @@ w_pretendtype = space.getattr(w_obj, space.wrap('__class__')) if space.is_w(w_pretendtype, space.type(w_obj)): return False # common case: obj.__class__ is type(obj) - w_result = space.issubtype(w_pretendtype, w_klass_or_tuple) + w_result = space.issubtype(w_pretendtype, w_klass_or_tuple, + allow_override) except OperationError, e: if e.async(space): raise @@ -78,13 +87,6 @@ oldstyleinst = space.interpclass_w(w_obj) if isinstance(oldstyleinst, W_InstanceObject): return oldstyleinst.w_class.is_subclass_of(oldstyleclass) - # -- case (anything, tuple) - # XXX it might be risky that the JIT sees this - if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)): - for w_klass in space.fixedview(w_klass_or_tuple): - if abstract_isinstance_w(space, w_obj, w_klass): - return True - return False return _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple) @jit.dont_look_inside @@ -118,12 +120,21 @@ @jit.unroll_safe -def abstract_issubclass_w(space, w_derived, w_klass_or_tuple): +def abstract_issubclass_w(space, w_derived, w_klass_or_tuple, + allow_override=False): """Implementation for the full 'issubclass(derived, klass_or_tuple)'.""" + # -- case (class-like-object, tuple-of-classes) + # XXX it might be risky that the JIT sees this + if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)): + for w_klass in space.fixedview(w_klass_or_tuple): + if abstract_issubclass_w(space, w_derived, w_klass, allow_override): + return True + return False + # -- case (type, type) try: - w_result = space.issubtype(w_derived, w_klass_or_tuple) + w_result = space.issubtype(w_derived, w_klass_or_tuple, allow_override) except OperationError, e: # if one of the args was not a type, ignore it if not e.match(space, space.w_TypeError): raise # propagate other errors @@ -140,14 +151,6 @@ check_class(space, w_derived, "issubclass() arg 1 must be a class") # from here on, we are sure that w_derived is a class-like object - # -- case (class-like-object, tuple-of-classes) - # XXX it might be risky that the JIT sees this - if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)): - for w_klass in space.fixedview(w_klass_or_tuple): - if abstract_issubclass_w(space, w_derived, w_klass): - return True - return False - # -- case (class-like-object, abstract-class) check_class(space, w_klass_or_tuple, "issubclass() arg 2 must be a class, type," @@ -193,13 +196,15 @@ """Check whether a class 'cls' is a subclass (i.e., a derived class) of another class. When using a tuple as the second argument, check whether 'cls' is a subclass of any of the classes listed in the tuple.""" - return space.wrap(abstract_issubclass_w(space, w_cls, w_klass_or_tuple)) + result = abstract_issubclass_w(space, w_cls, w_klass_or_tuple, True) + return space.wrap(result) def isinstance(space, w_obj, w_klass_or_tuple): """Check whether an object is an instance of a class (or of a subclass thereof). When using a tuple as the second argument, check whether 'obj' is an instance of any of the classes listed in the tuple.""" - return space.wrap(abstract_isinstance_w(space, w_obj, w_klass_or_tuple)) + result = abstract_isinstance_w(space, w_obj, w_klass_or_tuple, True) + return space.wrap(result) # avoid namespace pollution app_issubclass = issubclass; del issubclass Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py (original) +++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py Wed Jun 30 17:13:07 2010 @@ -182,3 +182,23 @@ assert not issubclass(BSub1, BSub2) assert not issubclass(MyInst, BSub1) assert not issubclass(BSub1, MyInst) + + def test_overriding(self): + class ABC(type): + + def __instancecheck__(cls, inst): + """Implement isinstance(inst, cls).""" + return any(cls.__subclasscheck__(c) + for c in set([type(inst), inst.__class__])) + + def __subclasscheck__(cls, sub): + """Implement issubclass(sub, cls).""" + candidates = cls.__dict__.get("__subclass__", set()) | set([cls]) + return any(c in candidates for c in sub.mro()) + class Integer: + + __metaclass__ = ABC + + __subclass__ = set([int]) + assert issubclass(int, Integer) + assert issubclass(int, (Integer,)) Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/descroperation.py Wed Jun 30 17:13:07 2010 @@ -465,18 +465,21 @@ space.wrap("coercion should return None or 2-tuple")) return w_res - def issubtype(space, w_sub, w_type): - w_check = space.lookup(w_type, "__subclasscheck__") - if w_check is None: - raise OperationError(space.w_TypeError, - space.wrap("issubclass not supported here")) - return space.get_and_call_function(w_check, w_type, w_sub) - - def isinstance(space, w_inst, w_type): - w_check = space.lookup(w_type, "__instancecheck__") - if w_check is not None: - return space.get_and_call_function(w_check, w_type, w_inst) - return space.issubtype(space.type(w_inst), w_type) + def issubtype(space, w_sub, w_type, allow_override=False): + if allow_override: + w_check = space.lookup(w_type, "__subclasscheck__") + if w_check is None: + raise OperationError(space.w_TypeError, + space.wrap("issubclass not supported here")) + return space.get_and_call_function(w_check, w_type, w_sub) + return space._type_issubtype(w_sub, w_type) + + def isinstance(space, w_inst, w_type, allow_override=False): + if allow_override: + w_check = space.lookup(w_type, "__instancecheck__") + if w_check is not None: + return space.get_and_call_function(w_check, w_type, w_inst) + return space.issubtype(space.type(w_inst), w_type, allow_override) Modified: pypy/branch/fast-forward/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/objspace.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/objspace.py Wed Jun 30 17:13:07 2010 @@ -508,3 +508,8 @@ def raise_key_error(self, w_key): e = self.call_function(self.w_KeyError, w_key) raise OperationError(self.w_KeyError, e) + + def _type_issubtype(self, w_sub, w_type): + if isinstance(w_sub, W_TypeObject) and isinstance(w_type, W_TypeObject): + return self.wrap(w_sub.issubtype(w_type)) + raise OperationError(self.w_TypeError, self.wrap("need type objects")) Modified: pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py (original) +++ pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py Wed Jun 30 17:13:07 2010 @@ -13,6 +13,22 @@ space.call_method(l, 'append', space.w_False) assert space.nonzero(l) is space.w_True + def test_isinstance_and_issubtype_ignore_special(self): + space = self.space + w_tup = space.appexec((), """(): + class Meta(type): + def __subclasscheck__(mcls, cls): + return False + class Base: + __metaclass__ = Meta + class Sub(Base): + pass + return Base, Sub""") + w_base, w_sub = space.unpackiterable(w_tup) + assert space.is_true(space.issubtype(w_sub, w_base)) + w_inst = space.call_function(w_sub) + assert space.isinstance_w(w_inst, w_base) + class AppTest_Descroperation: OPTIONS = {} From benjamin at codespeak.net Wed Jun 30 17:45:30 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 17:45:30 +0200 (CEST) Subject: [pypy-svn] r75687 - in pypy/branch/fast-forward/pypy/objspace/std: . test Message-ID: <20100630154530.751E4282BE3@codespeak.net> Author: benjamin Date: Wed Jun 30 17:45:28 2010 New Revision: 75687 Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py pypy/branch/fast-forward/pypy/objspace/std/typeobject.py pypy/branch/fast-forward/pypy/objspace/std/typetype.py Log: support __abstractmethods__ Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/objecttype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/objecttype.py Wed Jun 30 17:45:28 2010 @@ -47,7 +47,16 @@ raise operationerrfmt(space.w_TypeError, "__class__ assignment: '%s' object layout differs from '%s'", w_oldcls.getname(space, '?'), w_newcls.getname(space, '?')) - + + +app = gateway.applevel(""" +def _abstract_method_error(typ): + methods = ", ".join(sorted(typ.__abstractmethods__)) + err = "Can't instantiate abstract class %s with abstract methods %s" + raise TypeError(err % (methods, typ.__name__)) +""") +_abstract_method_error = app.interphook("_abstract_method_error") + def descr__new__(space, w_type, __args__): from pypy.objspace.std.objectobject import W_ObjectObject @@ -63,6 +72,8 @@ raise OperationError(space.w_TypeError, space.wrap("default __new__ takes " "no parameters")) + if w_type.is_abstract(): + _abstract_method_error(space, w_type) w_obj = space.allocate_instance(W_ObjectObject, w_type) return w_obj Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py Wed Jun 30 17:45:28 2010 @@ -103,6 +103,14 @@ class AppTestTypeObject: + def test_abstract_methods(self): + class X(object): + pass + X.__abstractmethods__ = ("meth",) + raises(TypeError, X) + del X.__abstractmethods__ + X() + def test_call_type(self): assert type(42) is int C = type('C', (object,), {'x': lambda: 42}) Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Wed Jun 30 17:45:28 2010 @@ -15,6 +15,7 @@ from copy_reg import _HEAPTYPE _CPYTYPE = 1 # used for non-heap types defined in C +_ABSTRACT = 1 << 2 # from compiler/misc.py @@ -358,6 +359,15 @@ def is_cpytype(w_self): return w_self.__flags__ & _CPYTYPE + def is_abstract(w_self): + return w_self.__flags__ & _ABSTRACT + + def set_abstract(w_self, abstract): + if abstract: + w_self.__flags__ |= _ABSTRACT + else: + w_self.__flags__ &= ~_ABSTRACT + def issubtype(w_self, w_type): w_self = hint(w_self, promote=True) w_type = hint(w_type, promote=True) Modified: pypy/branch/fast-forward/pypy/objspace/std/typetype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typetype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typetype.py Wed Jun 30 17:45:28 2010 @@ -206,6 +206,30 @@ w_type.mutated() w_type.dict_w['__module__'] = w_value +def descr_get___abstractmethods__(space, w_type): + w_type = _check(space, w_type) + try: + return w_type.dict_w["__abstractmethods__"] + except KeyError: + raise OperationError(space.w_AttributeError, + space.wrap("__abstractmethods__")) + +def descr_set___abstractmethods__(space, w_type, w_new): + w_type = _check(space, w_type) + w_type.dict_w["__abstractmethods__"] = w_new + w_type.mutated() + w_type.set_abstract(space.is_true(w_new)) + +def descr_del___abstractmethods__(space, w_type): + w_type = _check(space, w_type) + try: + del w_type.dict_w["__abstractmethods__"] + except KeyError: + raise OperationError(space.w_AttributeError, + space.wrap("__abstractmethods__")) + w_type.mutated() + w_type.set_abstract(False) + def descr___subclasses__(space, w_type): """Return the list of immediate subclasses.""" w_type = _check(space, w_type) @@ -224,6 +248,9 @@ mro = gateway.interp2app(descr_mro), __flags__ = GetSetProperty(descr__flags), __module__ = GetSetProperty(descr_get__module, descr_set__module), + __abstractmethods__ = GetSetProperty(descr_get___abstractmethods__, + descr_set___abstractmethods__, + descr_del___abstractmethods__), __subclasses__ = gateway.interp2app(descr___subclasses__), __weakref__ = weakref_descr, ) From benjamin at codespeak.net Wed Jun 30 17:52:52 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 17:52:52 +0200 (CEST) Subject: [pypy-svn] r75688 - in pypy/branch/fast-forward/pypy/module/operator: . test Message-ID: <20100630155252.8A748282BDE@codespeak.net> Author: benjamin Date: Wed Jun 30 17:52:51 2010 New Revision: 75688 Modified: pypy/branch/fast-forward/pypy/module/operator/__init__.py pypy/branch/fast-forward/pypy/module/operator/app_operator.py pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py Log: implement operator.methodcaller Modified: pypy/branch/fast-forward/pypy/module/operator/__init__.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/operator/__init__.py (original) +++ pypy/branch/fast-forward/pypy/module/operator/__init__.py Wed Jun 30 17:52:51 2010 @@ -21,7 +21,7 @@ 'countOf', 'delslice', 'getslice', 'indexOf', 'isMappingType', 'isNumberType', 'isSequenceType', 'repeat', 'setslice', - 'attrgetter', 'itemgetter' + 'attrgetter', 'itemgetter', 'methodcaller', ] for name in app_names: Modified: pypy/branch/fast-forward/pypy/module/operator/app_operator.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/operator/app_operator.py (original) +++ pypy/branch/fast-forward/pypy/module/operator/app_operator.py Wed Jun 30 17:52:51 2010 @@ -80,7 +80,7 @@ return tuple(list) return result - + class itemgetter(object): def __init__(self, item, *args): @@ -96,3 +96,12 @@ return result +class methodcaller(object): + + def __init__(self, method_name, *args, **kwargs): + self.method_name = method_name + self.args = args + self.kwargs = kwargs + + def __call__(self, obj): + return getattr(obj, self.method_name)(*self.args, **self.kwargs) Modified: pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py (original) +++ pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py Wed Jun 30 17:52:51 2010 @@ -171,3 +171,13 @@ assert operator.irepeat(a, 1) is a assert a == [0, 1, 2, 0, 1, 2] + def test_methodcaller(self): + from operator import methodcaller + class X(object): + def method(self, arg1=2, arg2=3): + return arg1, arg2 + x = X() + assert methodcaller("method")(x) == (2, 3) + assert methodcaller("method", 4)(x) == (4, 3) + assert methodcaller("method", 4, 5)(x) == (4, 5) + assert methodcaller("method", 4, arg2=42)(x) == (4, 42) From benjamin at codespeak.net Wed Jun 30 17:54:27 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 17:54:27 +0200 (CEST) Subject: [pypy-svn] r75689 - pypy/branch/fast-forward/pypy/objspace/std Message-ID: <20100630155427.14E7F282BDE@codespeak.net> Author: benjamin Date: Wed Jun 30 17:54:25 2010 New Revision: 75689 Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Log: use same flag as cpython Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Wed Jun 30 17:54:25 2010 @@ -15,7 +15,7 @@ from copy_reg import _HEAPTYPE _CPYTYPE = 1 # used for non-heap types defined in C -_ABSTRACT = 1 << 2 +_ABSTRACT = 1 << 20 # from compiler/misc.py From jcreigh at codespeak.net Wed Jun 30 17:57:59 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 30 Jun 2010 17:57:59 +0200 (CEST) Subject: [pypy-svn] r75690 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100630155759.86071282BDE@codespeak.net> Author: jcreigh Date: Wed Jun 30 17:57:58 2010 New Revision: 75690 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: kill force_mc, _start_block and _stop_block. Use remap_frame_layout from jump.py in _emit_call_64 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Wed Jun 30 17:57:58 2010 @@ -29,6 +29,7 @@ from pypy.jit.backend.x86.support import values_array from pypy.rlib.debug import debug_print from pypy.rlib import rgc +from pypy.jit.backend.x86.jump import remap_frame_layout # our calling convention - we pass first 6 args in registers # and the rest stays on the stack @@ -68,6 +69,12 @@ # not to write half-instruction self._reserved_bytes = 64 + def get_relative_pos(self): + return self._mc.get_relative_pos() + + def overwrite(self, pos, listofchars): + return self._mc.overwrite(pos, listofchars) + def bytes_free(self): return self._mc._size - self._mc.get_relative_pos() @@ -222,29 +229,28 @@ self.float_const_abs_addr = float_constants + 16 def _build_malloc_fixedsize_slowpath(self): - mc = self.mc._mc # ---------- first helper for the slow path of malloc ---------- - self.malloc_fixedsize_slowpath1 = mc.tell() + self.malloc_fixedsize_slowpath1 = self.mc.tell() if self.cpu.supports_floats: # save the XMM registers in for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8 - mc.MOVSD_sx((WORD*2)+8*i, i) - mc.SUB(edx, eax) # compute the size we want + self.mc.MOVSD_sx((WORD*2)+8*i, i) + self.mc.SUB(edx, eax) # compute the size we want if IS_X86_32: - mc.MOV_sr(WORD, edx.value) # save it as the new argument + self.mc.MOV_sr(WORD, edx.value) # save it as the new argument elif IS_X86_64: # FIXME: We can't just clobber rdi like this, can we? - mc.MOV_rr(edi.value, edx.value) + self.mc.MOV_rr(edi.value, edx.value) addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr() - mc.JMP(imm(addr)) # tail call to the real malloc + self.mc.JMP(imm(addr)) # tail call to the real malloc # ---------- second helper for the slow path of malloc ---------- - self.malloc_fixedsize_slowpath2 = mc.tell() + self.malloc_fixedsize_slowpath2 = self.mc.tell() if self.cpu.supports_floats: # restore the XMM registers for i in range(self.cpu.NUM_REGS):# from where they were saved - mc.MOVSD_xs(i, (WORD*2)+8*i) + self.mc.MOVSD_xs(i, (WORD*2)+8*i) nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() - mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX - mc.RET() + self.mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX + self.mc.RET() self.mc.done() def assemble_loop(self, inputargs, operations, looptoken): @@ -402,14 +408,14 @@ # Also, make sure this is consistent with FRAME_FIXED_SIZE. return self._patchable_stackadjust() - def _call_footer(self, mc): - mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD) + def _call_footer(self): + self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD) for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1): - mc.POP(self.cpu.CALLEE_SAVE_REGISTERS[i]) + self.mc.POP(self.cpu.CALLEE_SAVE_REGISTERS[i]) - mc.POP(ebp) - mc.RET() + self.mc.POP(ebp) + self.mc.RET() def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth): if IS_X86_64: @@ -533,23 +539,6 @@ finally: Box._extended_display = _prev - def _start_block(self): - # Return a 'mc' that can be used to write an "atomic" block, - # i.e. one that will not contain any JMP. - mc = self.mc._mc - if not we_are_translated(): - self._block_started_mc = (self.mc, mc.tell()) - self.mc = "block started" - return mc - - def _stop_block(self): - if not we_are_translated(): - assert self.mc == "block started" - self.mc, orgpos = self._block_started_mc - assert 0 <= self.mc._mc.tell() - orgpos <= 58, ( - "too many bytes in _start_block/_stop_block pair") - del self._block_started_mc - # ------------------------------------------------------------ def mov(self, from_loc, to_loc): @@ -695,53 +684,46 @@ return self.implement_guard(guard_token, false_cond) return genop_cmp_guard_float - # We need to specialize on force_mc because if force_mc is True, "mc" will - # be a MachineCodeBlock, whereas if it is False, "mc" will be a - # MachineCodeBlockWrapper - @specialize.arg(5) - def _emit_call(self, x, arglocs, start=0, tmp=eax, force_mc=False, - mc=None): + def _emit_call(self, x, arglocs, start=0, tmp=eax): if IS_X86_64: - return self._emit_call_64(x, arglocs, start, tmp, force_mc, mc) + return self._emit_call_64(x, arglocs, start) - if not force_mc: - mc = self.mc p = 0 n = len(arglocs) for i in range(start, n): loc = arglocs[i] if isinstance(loc, RegLoc): if loc.is_xmm: - mc.MOVSD_sx(p, loc.value) + self.mc.MOVSD_sx(p, loc.value) else: - mc.MOV_sr(p, loc.value) + self.mc.MOV_sr(p, loc.value) p += round_up_to_4(loc.width) p = 0 for i in range(start, n): loc = arglocs[i] if not isinstance(loc, RegLoc): if loc.width == 8: - mc.MOVSD(xmm0, loc) - mc.MOVSD_sx(p, xmm0.value) + self.mc.MOVSD(xmm0, loc) + self.mc.MOVSD_sx(p, xmm0.value) else: - mc.MOV(tmp, loc) - mc.MOV_sr(p, tmp.value) + self.mc.MOV(tmp, loc) + self.mc.MOV_sr(p, tmp.value) p += round_up_to_4(loc.width) self._regalloc.reserve_param(p//WORD) # x is a location - mc.CALL(x) + self.mc.CALL(x) self.mark_gc_roots() - @specialize.arg(5) - def _emit_call_64(self, x, arglocs, start=0, tmp=eax, force_mc=False, mc=None): - if not force_mc: - mc = self.mc + def _emit_call_64(self, x, arglocs, start=0): + src_locs = [] + dst_locs = [] + xmm_src_locs = [] + xmm_dst_locs = [] + pass_on_stack = [] # In reverse order for use with pop() unused_gpr = [r9, r8, ecx, edx, esi, edi] unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0] - pass_in_reg = {} - pass_on_stack = [] for i in range(start, len(arglocs)): loc = arglocs[i] @@ -750,72 +732,44 @@ # XXX: Should be much simplier to tell whether a location is a float! if (isinstance(loc, RegLoc) and loc.is_xmm) or (isinstance(loc, StackLoc) and loc.type == FLOAT): if len(unused_xmm) > 0: - pass_in_reg[unused_xmm.pop()] = loc + xmm_src_locs.append(loc) + xmm_dst_locs.append(unused_xmm.pop()) else: pass_on_stack.append(loc) else: if len(unused_gpr) > 0: - pass_in_reg[unused_gpr.pop()] = loc + src_locs.append(loc) + dst_locs.append(unused_gpr.pop()) else: pass_on_stack.append(loc) # Emit instructions to pass the stack arguments + # XXX: Would be nice to let remap_frame_layout take care of this, but + # we'd need to create something like StackLoc, but relative to esp, + # and I don't know if it's worth it. for i in range(len(pass_on_stack)): loc = pass_on_stack[i] if isinstance(loc, StackLoc): if loc.type == FLOAT: - mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) - mc.MOVSD_sx(i*WORD, X86_64_XMM_SCRATCH_REG.value) + self.mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) + self.mc.MOVSD_sx(i*WORD, X86_64_XMM_SCRATCH_REG.value) else: - if not force_mc: - mc.ensure_bytes_available(32) - mc.MOV(X86_64_SCRATCH_REG, loc) - mc.MOV_sr(i*WORD, X86_64_SCRATCH_REG.value) + self.mc.ensure_bytes_available(32) + self.mc.MOV(X86_64_SCRATCH_REG, loc) + self.mc.MOV_sr(i*WORD, X86_64_SCRATCH_REG.value) else: assert isinstance(loc, RegLoc) if loc.is_xmm: - mc.MOVSD_sx(i*WORD, loc.value) + self.mc.MOVSD_sx(i*WORD, loc.value) else: - mc.MOV_sr(i*WORD, loc.value) - - previous_len = sys.maxint # dummy value to start loop - while 0 < len(pass_in_reg) < previous_len: - previous_len = len(pass_in_reg) - # XXX: Maybe a little slow to call items() and values() so much? - for reg, loc in pass_in_reg.items(): - if reg == loc: - # Happy coincidence, do nothing - del pass_in_reg[reg] - elif reg not in pass_in_reg.values(): - if reg.is_xmm: - mc.MOVSD(reg, loc) - else: - mc.MOV(reg, loc) + self.mc.MOV_sr(i*WORD, loc.value) - del pass_in_reg[reg] - - if len(pass_in_reg) > 0: - # Rats. There is a "cycle". eg, r9 contains the value that we want - # to pass in r8, but r8 contains the value we want to pass in r9, - # so we can't just clobber r8. - # - # There's probably some clever way we could handle this, but we - # just temporarily dump the registers to the stack and then copy - # back to the correct registers. Hopefully this doesn't happen too - # often anyway. - # - # FIXME: Use of PUSH/POP will fail with XMM registers - items = pass_in_reg.items() - for reg, loc in items: - mc.PUSH(loc) - - for i in range(len(items)-1, -1, -1): - reg, loc = items[i] - mc.POP(reg) + # Handle register arguments + remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG) + remap_frame_layout(self, xmm_src_locs, xmm_dst_locs, X86_64_XMM_SCRATCH_REG) self._regalloc.reserve_param(len(pass_on_stack)) - mc.CALL(x) - + self.mc.CALL(x) self.mark_gc_roots() def call(self, addr, args, res): @@ -1177,10 +1131,10 @@ self.mc.CMP(locs[0], locs[1]) return self.implement_guard(guard_token, 'NE') - def _cmp_guard_class(self, mc, locs): + def _cmp_guard_class(self, locs): offset = self.cpu.vtable_offset if offset is not None: - mc.CMP(mem(locs[0], offset), locs[1]) + self.mc.CMP(mem(locs[0], offset), locs[1]) else: # XXX hard-coded assumption: to go from an object to its class # we use the following algorithm: @@ -1198,27 +1152,25 @@ type_info_group = llop.gc_get_type_info_group(llmemory.Address) type_info_group = rffi.cast(lltype.Signed, type_info_group) expected_typeid = (classptr - sizeof_ti - type_info_group) >> 2 - mc.CMP16(mem(locs[0], 0), ImmedLoc(expected_typeid)) + self.mc.CMP16(mem(locs[0], 0), ImmedLoc(expected_typeid)) def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, ign_2): - mc = self._start_block() - self._cmp_guard_class(mc, locs) - self._stop_block() + self.mc.ensure_bytes_available(256) + self._cmp_guard_class(locs) return self.implement_guard(guard_token, 'NE') def genop_guard_guard_nonnull_class(self, ign_1, guard_op, guard_token, locs, ign_2): - mc = self._start_block() - mc.CMP(locs[0], imm(1)) + self.mc.ensure_bytes_available(256) + self.mc.CMP(locs[0], imm(1)) # Patched below - mc.J_il8(rx86.Conditions['B'], 0) - jb_location = mc.get_relative_pos() - self._cmp_guard_class(mc, locs) + self.mc.J_il8(rx86.Conditions['B'], 0) + jb_location = self.mc.get_relative_pos() + self._cmp_guard_class(locs) # patch the JB above - offset = mc.get_relative_pos() - jb_location + offset = self.mc.get_relative_pos() - jb_location assert 0 < offset <= 127 - mc.overwrite(jb_location-1, [chr(offset)]) - self._stop_block() + self.mc.overwrite(jb_location-1, [chr(offset)]) # return self.implement_guard(guard_token, 'NE') @@ -1496,41 +1448,39 @@ # _assemble_bootstrap_code(). The LEA below throws away most # of the frame, including all the PUSHes that we did just above. - # XXX: using self.mc instead of mc to make translation pass - self._call_footer(self.mc) + self._call_footer() self.mc.done() self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr def generate_failure(self, fail_index, locs, exc, locs_are_ref): - mc = self.mc - mc._mc.begin_reuse_scratch_register() + self.mc._mc.begin_reuse_scratch_register() for i in range(len(locs)): loc = locs[i] if isinstance(loc, RegLoc): if loc.is_xmm: adr = self.fail_boxes_float.get_addr_for_num(i) - mc.MOVSD(heap(adr), loc) + self.mc.MOVSD(heap(adr), loc) else: if locs_are_ref[i]: adr = self.fail_boxes_ptr.get_addr_for_num(i) else: adr = self.fail_boxes_int.get_addr_for_num(i) - mc.MOV(heap(adr), loc) + self.mc.MOV(heap(adr), loc) for i in range(len(locs)): loc = locs[i] if not isinstance(loc, RegLoc): if isinstance(loc, StackLoc) and loc.type == FLOAT: - mc.MOVSD_xb(xmm0.value, loc.value) + self.mc.MOVSD_xb(xmm0.value, loc.value) adr = self.fail_boxes_float.get_addr_for_num(i) - mc.MOVSD(heap(adr), xmm0) + self.mc.MOVSD(heap(adr), xmm0) else: if locs_are_ref[i]: adr = self.fail_boxes_ptr.get_addr_for_num(i) else: adr = self.fail_boxes_int.get_addr_for_num(i) - mc.MOV(eax, loc) - mc.MOV(heap(adr), eax) - mc._mc.end_reuse_scratch_register() + self.mc.MOV(eax, loc) + self.mc.MOV(heap(adr), eax) + self.mc._mc.end_reuse_scratch_register() # we call a provided function that will # - call our on_leave_jitted_hook which will mark @@ -1538,12 +1488,12 @@ # avoid unwarranted freeing # - optionally save exception depending on the flag addr = self.cpu.get_on_leave_jitted_int(save_exception=exc) - mc.CALL(imm(addr)) + self.mc.CALL(imm(addr)) - mc.MOV(eax, imm(fail_index)) + self.mc.MOV(eax, imm(fail_index)) # exit function - self._call_footer(mc) + self._call_footer() # FIXME: I changed the third argument to this method, but I don't know # what to do with @specialize @@ -1603,7 +1553,7 @@ # Write a call to the direct_bootstrap_code of the target assembler self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2, tmp=eax) - mc = self._start_block() + self.mc.ensure_bytes_available(256) if op.result is None: assert result_loc is None value = self.cpu.done_with_this_frame_void_v @@ -1619,24 +1569,24 @@ value = self.cpu.done_with_this_frame_float_v else: raise AssertionError(kind) - mc.CMP(eax, imm(value)) + self.mc.CMP(eax, imm(value)) # patched later - mc.J_il8(rx86.Conditions['E'], 0) # goto B if we get 'done_with_this_frame' - je_location = mc.get_relative_pos() + self.mc.J_il8(rx86.Conditions['E'], 0) # goto B if we get 'done_with_this_frame' + je_location = self.mc.get_relative_pos() # # Path A: use assembler_helper_adr self._emit_call(imm(self.assembler_helper_adr), [eax, arglocs[1]], 0, - tmp=ecx, force_mc=True, mc=mc) + tmp=ecx) if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT: - mc.FSTP_b(result_loc.value) + self.mc.FSTP_b(result_loc.value) #else: result_loc is already either eax or None, checked below - mc.JMP_l8(0) # jump to done, patched later - jmp_location = mc.get_relative_pos() + self.mc.JMP_l8(0) # jump to done, patched later + jmp_location = self.mc.get_relative_pos() # # Path B: fast path. Must load the return value, and reset the token offset = jmp_location - je_location assert 0 < offset <= 127 - mc.overwrite(je_location - 1, [chr(offset)]) + self.mc.overwrite(je_location - 1, [chr(offset)]) # # Reset the vable token --- XXX really too much special logic here:-( if self.cpu.index_of_virtualizable >= 0: @@ -1644,8 +1594,8 @@ fielddescr = self.cpu.vable_token_descr assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset - mc.MOV(eax, arglocs[1]) - mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + self.mc.MOV(eax, arglocs[1]) + self.mc.MOV(addr_add(eax, imm(ofs)), imm(0)) # in the line above, TOKEN_NONE = 0 # if op.result is not None: @@ -1654,25 +1604,24 @@ if kind == FLOAT: xmmtmp = X86XMMRegisterManager.all_regs[0] adr = self.fail_boxes_float.get_addr_for_num(0) - mc.MOVSD(xmmtmp, heap(adr)) - mc.MOVSD(result_loc, xmmtmp) + self.mc.MOVSD(xmmtmp, heap(adr)) + self.mc.MOVSD(result_loc, xmmtmp) else: assert result_loc is eax if kind == INT: adr = self.fail_boxes_int.get_addr_for_num(0) - mc.MOV(eax, heap(adr)) + self.mc.MOV(eax, heap(adr)) elif kind == REF: adr = self.fail_boxes_ptr.get_addr_for_num(0) - mc.XOR(eax, eax) - mc.XCHG(eax, heap(adr)) + self.mc.XOR(eax, eax) + self.mc.XCHG(eax, heap(adr)) else: raise AssertionError(kind) # # Here we join Path A and Path B again - offset = mc.get_relative_pos() - jmp_location + offset = self.mc.get_relative_pos() - jmp_location assert 0 <= offset <= 127 - mc.overwrite(jmp_location - 1, [chr(offset)]) - self._stop_block() + self.mc.overwrite(jmp_location - 1, [chr(offset)]) self.mc.CMP_bi(FORCE_INDEX_OFS, 0) return self.implement_guard(guard_token, 'L') @@ -1684,37 +1633,36 @@ cls = self.cpu.gc_ll_descr.has_write_barrier_class() assert cls is not None and isinstance(descr, cls) loc_base = arglocs[0] - mc = self._start_block() - mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs), + self.mc.ensure_bytes_available(256) + self.mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs), descr.jit_wb_if_flag_singlebyte) - mc.J_il8(rx86.Conditions['Z'], 0) # patched later - jz_location = mc.get_relative_pos() + self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later + jz_location = self.mc.get_relative_pos() # the following is supposed to be the slow path, so whenever possible # we choose the most compact encoding over the most efficient one. for i in range(len(arglocs)-1, -1, -1): - mc.PUSH(arglocs[i]) + self.mc.PUSH(arglocs[i]) if IS_X86_64: # We clobber these registers to pass the arguments, but that's # okay, because consider_cond_call_gc_wb makes sure that any # caller-save registers with values in them are present in arglocs, # so they are saved on the stack above and restored below - mc.MOV_rs(edi.value, 0) - mc.MOV_rs(esi.value, 8) + self.mc.MOV_rs(edi.value, 0) + self.mc.MOV_rs(esi.value, 8) # misaligned stack in the call, but it's ok because the write barrier # is not going to call anything more. Also, this assumes that the # write barrier does not touch the xmm registers. - mc.CALL(imm(descr.get_write_barrier_fn(self.cpu))) + self.mc.CALL(imm(descr.get_write_barrier_fn(self.cpu))) for i in range(len(arglocs)): loc = arglocs[i] assert isinstance(loc, RegLoc) - mc.POP(loc) + self.mc.POP(loc) # patch the JZ above - offset = mc.get_relative_pos() - jz_location + offset = self.mc.get_relative_pos() - jz_location assert 0 < offset <= 127 - mc.overwrite(jz_location-1, [chr(offset)]) - self._stop_block() + self.mc.overwrite(jz_location-1, [chr(offset)]) def genop_force_token(self, op, arglocs, resloc): # RegAlloc.consider_force_token ensures this: @@ -1751,13 +1699,12 @@ def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr, size, tid): - # don't use self.mc - mc = self._start_block() - mc.MOV(eax, heap(nursery_free_adr)) - mc.LEA(edx, addr_add(eax, imm(size))) - mc.CMP(edx, heap(nursery_top_adr)) - mc.J_il8(rx86.Conditions['NA'], 0) # patched later - jmp_adr = mc.get_relative_pos() + self.mc.ensure_bytes_available(256) + self.mc.MOV(eax, heap(nursery_free_adr)) + self.mc.LEA(edx, addr_add(eax, imm(size))) + self.mc.CMP(edx, heap(nursery_top_adr)) + self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later + jmp_adr = self.mc.get_relative_pos() # See comments in _build_malloc_fixedsize_slowpath for the # details of the two helper functions that we are calling below. @@ -1773,17 +1720,16 @@ # reserve room for the argument to the real malloc and the # 8 saved XMM regs self._regalloc.reserve_param(1+16) - mc.CALL(imm(slowpath_addr1)) + self.mc.CALL(imm(slowpath_addr1)) self.mark_gc_roots() slowpath_addr2 = self.malloc_fixedsize_slowpath2 - mc.CALL(imm(slowpath_addr2)) + self.mc.CALL(imm(slowpath_addr2)) - offset = mc.get_relative_pos() - jmp_adr + offset = self.mc.get_relative_pos() - jmp_adr assert 0 < offset <= 127 - mc.overwrite(jmp_adr-1, [chr(offset)]) - mc.MOV(addr_add(eax, imm(0)), imm(tid)) - mc.MOV(heap(nursery_free_adr), edx) - self._stop_block() + self.mc.overwrite(jmp_adr-1, [chr(offset)]) + self.mc.MOV(addr_add(eax, imm(0)), imm(tid)) + self.mc.MOV(heap(nursery_free_adr), edx) genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST genop_list = [Assembler386.not_implemented_op] * rop._LAST From benjamin at codespeak.net Wed Jun 30 18:26:32 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 18:26:32 +0200 (CEST) Subject: [pypy-svn] r75691 - pypy/branch/fast-forward/pypy/objspace/std Message-ID: <20100630162632.5F022282BDE@codespeak.net> Author: benjamin Date: Wed Jun 30 18:26:30 2010 New Revision: 75691 Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py Log: __subclasshook__ is a class method Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/branch/fast-forward/pypy/objspace/std/objecttype.py (original) +++ pypy/branch/fast-forward/pypy/objspace/std/objecttype.py Wed Jun 30 18:26:30 2010 @@ -207,7 +207,7 @@ __format__ = gateway.interp2app(descr___format__, unwrap_spec=[ObjSpace, gateway.W_Root, gateway.W_Root]), __subclasshook__ = gateway.interp2app(descr___subclasshook__, unwrap_spec= - [ObjSpace, Arguments]), + [ObjSpace, Arguments], as_classmethod=True), __init__ = gateway.interp2app(descr__init__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), ) From jcreigh at codespeak.net Wed Jun 30 18:40:55 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 30 Jun 2010 18:40:55 +0200 (CEST) Subject: [pypy-svn] r75692 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100630164055.E689C282BDE@codespeak.net> Author: jcreigh Date: Wed Jun 30 18:40:54 2010 New Revision: 75692 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: use rx86 calls instead of regloc calls when possible Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Wed Jun 30 18:40:54 2010 @@ -234,7 +234,7 @@ if self.cpu.supports_floats: # save the XMM registers in for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8 self.mc.MOVSD_sx((WORD*2)+8*i, i) - self.mc.SUB(edx, eax) # compute the size we want + self.mc.SUB_rr(edx.value, eax.value) # compute the size we want if IS_X86_32: self.mc.MOV_sr(WORD, edx.value) # save it as the new argument elif IS_X86_64: @@ -399,10 +399,10 @@ mc.done() def _call_header(self): - self.mc.PUSH(ebp) + self.mc.PUSH_r(ebp.value) self.mc.MOV_rr(ebp.value, esp.value) for regloc in self.cpu.CALLEE_SAVE_REGISTERS: - self.mc.PUSH(regloc) + self.mc.PUSH_r(regloc.value) # NB. the shape of the frame is hard-coded in get_basic_shape() too. # Also, make sure this is consistent with FRAME_FIXED_SIZE. @@ -412,9 +412,9 @@ self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD) for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1): - self.mc.POP(self.cpu.CALLEE_SAVE_REGISTERS[i]) + self.mc.POP_r(self.cpu.CALLEE_SAVE_REGISTERS[i].value) - self.mc.POP(ebp) + self.mc.POP_r(ebp.value) self.mc.RET() def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth): @@ -563,7 +563,7 @@ def regalloc_pop(self, loc): if isinstance(loc, RegLoc) and loc.is_xmm: self.mc.MOVSD_xs(loc.value, 0) - self.mc.ADD(esp, imm(2*WORD)) + self.mc.ADD_ri(esp.value, 2*WORD) elif WORD == 4 and isinstance(loc, StackLoc) and loc.width == 8: # XXX evil trick self.mc.POP_b(get_ebp_ofs(loc.position + 1)) @@ -904,7 +904,7 @@ genop_int_floordiv = genop_int_mod def genop_uint_floordiv(self, op, arglocs, resloc): - self.mc.XOR(edx, edx) + self.mc.XOR_rr(edx.value, edx.value) self.mc.DIV_r(ecx.value) def genop_new_with_vtable(self, op, arglocs, result_loc): @@ -1433,9 +1433,9 @@ # XXX if IS_X86_32: - mc.PUSH(ebx) + mc.PUSH_r(ebx.value) elif IS_X86_64: - mc.MOV(edi, ebx) + mc.MOV_rr(edi.value, ebx.value) # XXX: Correct to only align the stack on 64-bit? mc.AND_ri(esp.value, -16) else: @@ -1490,7 +1490,7 @@ addr = self.cpu.get_on_leave_jitted_int(save_exception=exc) self.mc.CALL(imm(addr)) - self.mc.MOV(eax, imm(fail_index)) + self.mc.MOV_ri(eax.value, fail_index) # exit function self._call_footer() @@ -1528,9 +1528,9 @@ if isinstance(resloc, StackLoc) and resloc.width == 8 and IS_X86_32: self.mc.FSTP_b(resloc.value) elif size == 1: - self.mc.AND(eax, imm(0xff)) + self.mc.AND_ri(eax.value, 0xff) elif size == 2: - self.mc.AND(eax, imm(0xffff)) + self.mc.AND_ri(eax.value, 0xffff) def genop_guard_call_may_force(self, op, guard_op, guard_token, arglocs, result_loc): @@ -1569,7 +1569,7 @@ value = self.cpu.done_with_this_frame_float_v else: raise AssertionError(kind) - self.mc.CMP(eax, imm(value)) + self.mc.CMP_ri(eax.value, value) # patched later self.mc.J_il8(rx86.Conditions['E'], 0) # goto B if we get 'done_with_this_frame' je_location = self.mc.get_relative_pos() @@ -1595,7 +1595,7 @@ assert isinstance(fielddescr, BaseFieldDescr) ofs = fielddescr.offset self.mc.MOV(eax, arglocs[1]) - self.mc.MOV(addr_add(eax, imm(ofs)), imm(0)) + self.mc.MOV_mi((eax.value, ofs), 0) # in the line above, TOKEN_NONE = 0 # if op.result is not None: @@ -1613,7 +1613,7 @@ self.mc.MOV(eax, heap(adr)) elif kind == REF: adr = self.fail_boxes_ptr.get_addr_for_num(0) - self.mc.XOR(eax, eax) + self.mc.XOR_rr(eax.value, eax.value) self.mc.XCHG(eax, heap(adr)) else: raise AssertionError(kind) @@ -1701,7 +1701,7 @@ size, tid): self.mc.ensure_bytes_available(256) self.mc.MOV(eax, heap(nursery_free_adr)) - self.mc.LEA(edx, addr_add(eax, imm(size))) + self.mc.LEA_rm(edx.value, (eax.value, size)) self.mc.CMP(edx, heap(nursery_top_adr)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr = self.mc.get_relative_pos() @@ -1728,7 +1728,7 @@ offset = self.mc.get_relative_pos() - jmp_adr assert 0 < offset <= 127 self.mc.overwrite(jmp_adr-1, [chr(offset)]) - self.mc.MOV(addr_add(eax, imm(0)), imm(tid)) + self.mc.MOV_mi((eax.value, 0), tid) self.mc.MOV(heap(nursery_free_adr), edx) genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST From benjamin at codespeak.net Wed Jun 30 18:50:07 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 18:50:07 +0200 (CEST) Subject: [pypy-svn] r75693 - in pypy/branch/fast-forward/pypy/module/operator: . test Message-ID: <20100630165007.55C96282BDE@codespeak.net> Author: benjamin Date: Wed Jun 30 18:50:06 2010 New Revision: 75693 Modified: pypy/branch/fast-forward/pypy/module/operator/app_operator.py pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py Log: allow dotted attributes to attrgetter Modified: pypy/branch/fast-forward/pypy/module/operator/app_operator.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/operator/app_operator.py (original) +++ pypy/branch/fast-forward/pypy/module/operator/app_operator.py Wed Jun 30 18:50:06 2010 @@ -68,18 +68,26 @@ class attrgetter(object): - def __init__(self, attr, *args): - self.attrs = args - self.attr = attr + def __init__(self, attr, *attrs): + self.attrs = (attr,) + attrs - def __call__(self, obj): - result = getattr(obj, self.attr) - - if self.attrs: - list = [result] + [getattr(obj, attr) for attr in self.attrs] - return tuple(list) + def _resolve_attr(self, obj, attr): + last = 0 + while True: + try: + dot = attr.find(".", last) + except AttributeError: + raise TypeError + if dot > 0: + obj = getattr(obj, attr[last:dot]) + last = dot + 1 + else: + return getattr(obj, attr[last:]) - return result + def __call__(self, obj): + if len(self.attrs) == 1: + return self._resolve_attr(obj, self.attrs[0]) + return tuple(self._resolve_attr(obj, attr) for attr in self.attrs) class itemgetter(object): Modified: pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py (original) +++ pypy/branch/fast-forward/pypy/module/operator/test/test_operator.py Wed Jun 30 18:50:06 2010 @@ -35,6 +35,16 @@ assert operator.itemgetter(2,10,5)(data) == ('2', '10', '5') raises(TypeError, operator.itemgetter(2, 'x', 5), data) + def test_dotted_attrgetter(self): + from operator import attrgetter + class A: + pass + a = A() + a.name = "hello" + a.child = A() + a.child.name = "world" + assert attrgetter("child.name")(a) == "world" + def test_concat(self): class Seq1: def __init__(self, lst): From benjamin at codespeak.net Wed Jun 30 20:14:20 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 20:14:20 +0200 (CEST) Subject: [pypy-svn] r75694 - pypy/branch/fast-forward/pypy/module/posix Message-ID: <20100630181420.CD403282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 20:14:18 2010 New Revision: 75694 Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Log: 2.6 is silly and raises an IOError here Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Wed Jun 30 20:14:18 2010 @@ -83,6 +83,12 @@ """Truncate a file to a specified length.""" try: os.ftruncate(fd, length) + except IOError, e: + # Python 2.6 raises an IOError here. Let's not repeat that mistake. + w_error = space.call_function(space.w_OSError, space.wrap(e.errno), + space.wrap(e.strerror), + space.wrap(e.filename)) + raise OperationError(space.w_OSError, w_error) except OSError, e: raise wrap_oserror(space, e) ftruncate.unwrap_spec = [ObjSpace, "c_int", r_longlong] From benjamin at codespeak.net Wed Jun 30 20:36:09 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 20:36:09 +0200 (CEST) Subject: [pypy-svn] r75695 - in pypy/branch/fast-forward/pypy/module/posix: . test Message-ID: <20100630183609.B8159282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 20:36:07 2010 New Revision: 75695 Modified: pypy/branch/fast-forward/pypy/module/posix/app_posix.py pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Log: validate file descriptors to fdopen Modified: pypy/branch/fast-forward/pypy/module/posix/app_posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/app_posix.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/app_posix.py Wed Jun 30 20:36:07 2010 @@ -72,7 +72,12 @@ """fdopen(fd [, mode='r' [, buffering]]) -> file_object Return an open file object connected to a file descriptor.""" - + # Validate fd + import fcntl + try: + fcntl.fcntl(fd, fcntl.F_GETFD) + except IOError, e: + raise OSError(e.errno, e.strerror, e.filename) return _fdopen(fd, mode, buffering) Modified: pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Wed Jun 30 20:36:07 2010 @@ -248,6 +248,7 @@ fd = posix.open(path, posix.O_RDONLY, 0777) f = posix.fdopen(fd, "r") f.close() + raises(OSError, posix.fdopen, fd) def test_fdopen_hackedbuiltins(self): "Same test, with __builtins__.file removed" From benjamin at codespeak.net Wed Jun 30 20:55:45 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 20:55:45 +0200 (CEST) Subject: [pypy-svn] r75696 - in pypy/branch/fast-forward/pypy/module/posix: . test Message-ID: <20100630185545.D07DB282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 20:55:43 2010 New Revision: 75696 Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Log: apparently execv must have at least one arg Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Wed Jun 30 20:55:43 2010 @@ -550,8 +550,12 @@ path: path of executable file args: iterable of strings """ + args_w = space.unpackiterable(w_args) + if len(args_w) < 1: + w_msg = space.wrap("execv() must have at least one argument") + raise OperationError(space.w_ValueError, w_msg) try: - os.execv(command, [space.str_w(i) for i in space.unpackiterable(w_args)]) + os.execv(command, [space.str_w(w_arg) for w_arg in args_w]) except OperationError, e: if not e.match(space, space.w_TypeError): raise Modified: pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Wed Jun 30 20:55:43 2010 @@ -349,6 +349,10 @@ os = self.posix raises(OSError, 'os.execv("saddsadsadsadsa", ["saddsadsasaddsa"])') + def test_execv_no_args(self): + os = self.posix + raises(ValueError, os.execv, "notepad", []) + def test_execv_raising2(self): os = self.posix def t(n): From jcreigh at codespeak.net Wed Jun 30 20:55:53 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 30 Jun 2010 20:55:53 +0200 (CEST) Subject: [pypy-svn] r75697 - in pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86: . test Message-ID: <20100630185553.49D1E282BDE@codespeak.net> Author: jcreigh Date: Wed Jun 30 20:55:51 2010 New Revision: 75697 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Log: 32-bit fixes Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/regloc.py Wed Jun 30 20:55:51 2010 @@ -230,11 +230,12 @@ for possible_code in unrolling_location_codes: if code == possible_code: val = getattr(loc, "value_" + possible_code)() - if self.WORD == 8 and possible_code == 'i': + if possible_code == 'i': offset = val - (self.tell() + 5) if rx86.fits_in_32bits(offset): _rx86_getattr(self, name + "_l")(val) else: + assert self.WORD == 8 self.MOV_ri(X86_64_SCRATCH_REG.value, val) _rx86_getattr(self, name + "_r")(X86_64_SCRATCH_REG.value) else: Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/rx86.py Wed Jun 30 20:55:51 2010 @@ -437,6 +437,11 @@ CMP_rm = insn(rex_w, '\x3B', register(1, 8), mem_reg_plus_const(2)) CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) + CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2)) + CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) + CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2)) + AND8_rr = insn(rex_w, '\x20', byte_register(1), byte_register(2,8), '\xC0') OR8_rr = insn(rex_w, '\x08', byte_register(1), byte_register(2,8), '\xC0') @@ -544,11 +549,6 @@ class X86_32_CodeBuilder(AbstractX86CodeBuilder): WORD = 4 - CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2)) - CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2)) - class X86_64_CodeBuilder(AbstractX86CodeBuilder): WORD = 8 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regloc.py Wed Jun 30 20:55:51 2010 @@ -1,6 +1,8 @@ from pypy.jit.backend.x86.regloc import * from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as from pypy.jit.backend.x86.assembler import heap +from pypy.jit.backend.x86.arch import IS_X86_64 +import py.test class LocationCodeBuilder32(CodeBuilder32, LocationCodeBuilder): pass @@ -20,6 +22,9 @@ assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') def test_reuse_scratch_register(): + if not IS_X86_64: + py.test.skip() + base_addr = 0xFEDCBA9876543210 cb = LocationCodeBuilder64() cb.begin_reuse_scratch_register() From benjamin at codespeak.net Wed Jun 30 21:00:47 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 21:00:47 +0200 (CEST) Subject: [pypy-svn] r75698 - in pypy/branch/fast-forward/pypy/module/posix: . test Message-ID: <20100630190047.9412E282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 21:00:44 2010 New Revision: 75698 Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Log: fix test Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Wed Jun 30 21:00:44 2010 @@ -550,19 +550,21 @@ path: path of executable file args: iterable of strings """ - args_w = space.unpackiterable(w_args) - if len(args_w) < 1: - w_msg = space.wrap("execv() must have at least one argument") - raise OperationError(space.w_ValueError, w_msg) try: - os.execv(command, [space.str_w(w_arg) for w_arg in args_w]) + args_w = space.unpackiterable(w_args) + if len(args_w) < 1: + w_msg = space.wrap("execv() must have at least one argument") + raise OperationError(space.w_ValueError, w_msg) + args = [space.str_w(w_arg) for w_arg in args_w] except OperationError, e: if not e.match(space, space.w_TypeError): raise msg = "execv() arg 2 must be an iterable of strings" raise OperationError(space.w_TypeError, space.wrap(str(msg))) + try: + os.execv(command, args) except OSError, e: - raise wrap_oserror(space, e) + raise wrap_oserror(space, e) execv.unwrap_spec = [ObjSpace, str, W_Root] def execve(space, command, w_args, w_env): Modified: pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py (original) +++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Wed Jun 30 21:00:44 2010 @@ -355,15 +355,13 @@ def test_execv_raising2(self): os = self.posix - def t(n): + for n in 3, [3, "a"]: try: os.execv("xxx", n) except TypeError,t: - assert t.args[0] == "execv() arg 2 must be an iterable of strings" + assert str(t) == "execv() arg 2 must be an iterable of strings" else: py.test.fail("didn't raise") - t(3) - t([3, "a"]) def test_execve(self): os = self.posix From benjamin at codespeak.net Wed Jun 30 21:09:36 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 21:09:36 +0200 (CEST) Subject: [pypy-svn] r75699 - pypy/branch/fast-forward/lib_pypy/_ctypes Message-ID: <20100630190936.257FF282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 21:09:12 2010 New Revision: 75699 Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/__init__.py Log: I suppose we should pretend we support this version Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/__init__.py ============================================================================== --- pypy/branch/fast-forward/lib_pypy/_ctypes/__init__.py (original) +++ pypy/branch/fast-forward/lib_pypy/_ctypes/__init__.py Wed Jun 30 21:09:12 2010 @@ -20,7 +20,7 @@ from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI -__version__ = '1.0.3' +__version__ = '1.1.0' #XXX platform dependant? RTLD_LOCAL = 0 RTLD_GLOBAL = 256 From benjamin at codespeak.net Wed Jun 30 21:14:21 2010 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Wed, 30 Jun 2010 21:14:21 +0200 (CEST) Subject: [pypy-svn] r75700 - pypy/branch/fast-forward/lib-python Message-ID: <20100630191421.C4B44282B9C@codespeak.net> Author: benjamin Date: Wed Jun 30 21:14:04 2010 New Revision: 75700 Modified: pypy/branch/fast-forward/lib-python/conftest.py Log: test_posix wants rawffi in a very roundabout way Modified: pypy/branch/fast-forward/lib-python/conftest.py ============================================================================== --- pypy/branch/fast-forward/lib-python/conftest.py (original) +++ pypy/branch/fast-forward/lib-python/conftest.py Wed Jun 30 21:14:04 2010 @@ -371,7 +371,7 @@ RegrTest('test_popen.py'), RegrTest('test_popen2.py'), RegrTest('test_poplib.py'), - RegrTest('test_posix.py'), + RegrTest('test_posix.py', usemodules="_rawffi"), RegrTest('test_posixpath.py'), RegrTest('test_pow.py', core=True), RegrTest('test_pprint.py', core=True), From jcreigh at codespeak.net Wed Jun 30 22:01:09 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 30 Jun 2010 22:01:09 +0200 (CEST) Subject: [pypy-svn] r75704 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test Message-ID: <20100630200109.4B4D9282B9C@codespeak.net> Author: jcreigh Date: Wed Jun 30 22:01:07 2010 New Revision: 75704 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Log: tweak test_call_many_arguments to catch case where a constant is passed on the stack Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_regalloc.py Wed Jun 30 22:01:07 2010 @@ -579,12 +579,15 @@ assert loop.token._x86_param_depth == self.expected_param_depth(2) def test_call_many_arguments(self): + # NB: The first and last arguments in the call are constants. This + # is primarily for x86-64, to ensure that loading a constant to an + # argument register or to the stack works correctly ops = ''' - [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9] - i10 = call(ConstClass(f10ptr), i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, descr=f10_calldescr) - finish(i10) + [i0, i1, i2, i3, i4, i5, i6, i7] + i8 = call(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr) + finish(i8) ''' - loop = self.interpret(ops, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + loop = self.interpret(ops, [2, 3, 4, 5, 6, 7, 8, 9]) assert self.getint(0) == 55 assert loop.token._x86_param_depth == self.expected_param_depth(10) From jcreigh at codespeak.net Wed Jun 30 22:18:56 2010 From: jcreigh at codespeak.net (jcreigh at codespeak.net) Date: Wed, 30 Jun 2010 22:18:56 +0200 (CEST) Subject: [pypy-svn] r75705 - pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86 Message-ID: <20100630201856.A0964282B9C@codespeak.net> Author: jcreigh Date: Wed Jun 30 22:18:54 2010 New Revision: 75705 Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Log: fix to allow constants to be passed to the stack (see r75704) Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Wed Jun 30 22:18:54 2010 @@ -749,8 +749,8 @@ # and I don't know if it's worth it. for i in range(len(pass_on_stack)): loc = pass_on_stack[i] - if isinstance(loc, StackLoc): - if loc.type == FLOAT: + if not isinstance(loc, RegLoc): + if isinstance(loc, StackLoc) and loc.type == FLOAT: self.mc.MOVSD(X86_64_XMM_SCRATCH_REG, loc) self.mc.MOVSD_sx(i*WORD, X86_64_XMM_SCRATCH_REG.value) else: @@ -758,7 +758,7 @@ self.mc.MOV(X86_64_SCRATCH_REG, loc) self.mc.MOV_sr(i*WORD, X86_64_SCRATCH_REG.value) else: - assert isinstance(loc, RegLoc) + # It's a register if loc.is_xmm: self.mc.MOVSD_sx(i*WORD, loc.value) else: